Rails按属性值过滤对象数组

时间:2012-04-09 06:58:49

标签: ruby-on-rails activerecord

所以我对db执行查询,我有一个完整的对象数组:

@attachments = Job.find(1).attachments

现在我有一个对象数组,我不想再执行另一个数据库查询,但我想根据Attachment对象的file_type过滤数组,这样我才能拥有文件类型为attachments的{​​{1}}列表,然后是文件类型为'logo'的其他attachments列表

这样的事情:

'image'

但是在内存中而不是数据库查询。

6 个答案:

答案 0 :(得分:161)

尝试:

这很好:

@logos = @attachments.select { |attachment| attachment.file_type == 'logo' }
@images = @attachments.select { |attachment| attachment.file_type == 'image' }

但是对于性能方面,你不需要两次迭代@attachments:

@logos , @images = [], []
@attachments.each do |attachment|
  @logos << attachment if attachment.file_type == 'logo'
  @images << attachment if attachment.file_type == 'image'
end

答案 1 :(得分:7)

如果您的附件是

@attachments = Job.find(1).attachments

这将是附件对象数组

使用select方法根据file_type进行过滤。

@logos = @attachments.select { |attachment| attachment.file_type == 'logo' }
@images = @attachments.select { |attachment| attachment.file_type == 'image' }

这不会触发任何数据库查询。

答案 2 :(得分:2)

你尝试过加载吗?

@attachments = Job.includes(:attachments).find(1).attachments

答案 3 :(得分:0)

您可以使用where进行过滤

Job.includes(:attachments).where(file_type: ["logo", "image"])

答案 4 :(得分:0)

我会略有不同。对查询进行结构化,使其仅检索您需要的内容并从那里进行拆分。

因此,请执行以下查询:

#                                vv or Job.find(1) vv
attachments = Attachment.where(job_id: @job.id, file_type: ["logo", "image"])
# or 
Job.includes(:attachments).where(id: your_job_id, attachments: { file_type: ["logo", "image"] })

然后对数据进行分区:

@logos, @images = attachments.partition { |attachment| attachment.file_type == "logo" }

这将以一种整齐而高效的方式获取您所需要的数据。

答案 5 :(得分:0)

对于较新版本的 ruby​​,您可以使用

@logos = @attachments.filter { |attachment| attachment.file_type == 'logo' }

参考:https://apidock.com/ruby/Array/filter