简体   繁体   English

如何在Ruby中为'每个循环'创建这个?

[英]How to create this 'for each loop' in Ruby?

Given: 鉴于:

class Author < ActiveRecord::Base
  has_many :articles
end

Upon receipt of a JSON file that includes the author's articles, I'd like to destroy the articles that are in the database for the author, but not included in the JSON file. 收到包含作者文章的JSON文件后,我想销毁作者数据库中的文章,但不包含在JSON文件中。 How can I create this 'for each loop'? 如何为每个循环创建“?”?

article_collection = @author.articles.all
unless article_collection.blank?
  article_collection.each do |article_from_collection|
    # How can I check on the next line if it's id is included in the params?
    if article_from_collection.arti_id "is not part of" params[:author][:articles_attributes]
      article_from_collection.destroy
    end
  end
end

How can I check on the 5th line, on basis of arti_id which is also included in the params, whether the article with that arti_id exists in the JSON input? 如何根据arti_id (也包含在参数中)检查第5行,是否有关于arti_id的文章存在于JSON输入中?

Should I perhaps build a collection of arti_id s in the parameters and then use .include? 我是否应该在参数中构建arti_id的集合然后使用.include? to see for each article in the DB, if it is in this collection? 要查看数据库中的每篇文章,是否在此集合中?

I tried the two lines below. 我尝试了以下两行。 The first returns false irrespective whether the article is included in the json or not. 无论文章是否包含在json中,第一个都返回false The second line returns the error TypeError Exception: no implicit conversion of Symbol into Integer . 第二行返回错误TypeError Exception: no implicit conversion of Symbol into Integer

if params[:author][:articles_attributes].include? article_from_collection.arti_id
if params[:author][:articles_attributes][:arti_id].include? article_from_collection.arti_id

params[:author] returns something like: params[:author]返回类似于:

{ "some_other_attributes"=>[ {"key"=>"value", ...},
                             {...} ],
  "articles_attributes"=>  [ {"arti_id"=>"string-id", "other_attributes"=>"value", ...},
                             {"arti_id"=>"string-id", "other_attributes"=>"value", ...} ]
}

You could do this with an ActiveRecord query 您可以使用ActiveRecord查询执行此操作

article_ids = params[:author][:article_attributes].map do |attrs|
  attrs[:arti_id]
end

@author.articles.where.not(id: article_ids).destroy_all

This will destroy all articles for the author whose ids are not in the article attributes you've been given. 这将摧毁作者的所有文章,其作者的ID不在您给出的文章属性中。

If you're confused about the query, it simply creates a NOT IN query which filters out the articles passed in and then destroys the ones that are left over. 如果您对查询感到困惑,它只会创建一个NOT IN查询,该查询会过滤掉传入的文章,然后销毁剩下的文章。

For this, you can first map out all the arti_id in a separate array variable, and then use the include? 为此,您可以先在单独的数组变量中映射出所有arti_id ,然后使用include? method or the exclude? 方法还是exclude? method to check if a particular id is in the array. 方法 ,以检查是否一个特定的ID是在数组中。

Example: 例:

article_ids = params[:author][:articles_attributes].map{ |art_attr| art_attr[:arti_id] }

and then in the loop: ( for using the include? method ) 然后在循环中:(用于使用include?方法)

article_collection = @author.articles.all
unless article_collection.blank?
  article_collection.each do |article_from_collection|
    # This is how you can handle it...
    unless article_ids.include? article_from_collection.arti_id 
      article_from_collection.destroy
    end
  end
end

or if you will prefer using exclude ? 或者如果您更喜欢使用exclude

article_collection = @author.articles.all
unless article_collection.blank?
  article_collection.each do |article_from_collection|
    # This is how you can handle it...
    if article_ids.exclude? article_from_collection.arti_id 
      article_from_collection.destroy
    end
  end
end

How about something like the following: 如下所示:

article_collection = @author.articles.all
params_article_ids = params[:author][:articles_attributes].collect{ |article_attrs| article_attrs[:arti_id]}

article_collection.reject{ |art| present_article_ids.include?(art.id)}.each(&:destroy)

I assume your params[:author][:articles_attributes] holds hashes of article attributes where each of them has an arti_id. 我假设你的params [:author] [:articles_attributes]包含文章属性的哈希值,其中每个属性都有一个arti_id。

At first I would return all article ids of the author: 首先,我将返回作者的所有文章ID:

all_article_ids = @author.articles.pluck(:arti_id)

Second, I collect all arti_ids from your article attributes you want to keep save: 其次,我从您要保存的文章属性中收集所有arti_ids:

ids = params[:author][:articles_attributes].map{|attr| attr.arti_id}

Now there are two arrays of ids. 现在有两个id数组。 I subtract the "ids" array from the "all_article_ids" and I get a new array of ids, which are not in the "ids" array. 我从“all_article_ids”中减去“ids”数组,然后得到一个新的id数组,这些数组不在“ids”数组中。 These are the ids of "all_article_ids", which should be destroyed. 这些是“all_article_ids”的ID,应该将其销毁。

@author.articles.destroy(all_article_ids - ids)

Is this what fits your needs? 这适合您的需求吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM