如果范围返回记录而不是空白,则仅将对象推送到数组中

时间:2014-09-04 19:03:06

标签: ruby activerecord ruby-on-rails-4

我有一个循环,它会击中几个范围,然后将结果推送到数组中。我遇到的问题是如果没有记录匹配范围,它仍然返回 ActiveRecord :: AssociationRelation [] 。如何过滤掉这些内容,以便我不能将它们放入我的阵列中?

示例:

class Snack
  belongs_to :member

  scope :red, -> { where(color: 'red') }
  scope :snacktypefind, -> (snacktypefind) { where(snacktype: snacktypefind) }
end

class Member
  has_many :snacks

 def find_snacks(snacktypes)
    returnarray = []
    snacktypes.each do |snacktype|
       returnarray << self.snacks.red.snacktypefind(snacktype)
    end
  return returnarray
 end

end

然后在一个视图中说我想:

 <% @member.find_snacks(['bannana','orange']).each do |snack| %>
    <li>snack.name</li>
 <% end %>

在上面的例子中,我希望数组为[],而不是:

[#<ActiveRecord::AssociationRelation []>, #<ActiveRecord::AssociationRelation []>]

这次我做错了什么傻事?再次感谢您提供任何帮助!

2 个答案:

答案 0 :(得分:1)

哇,你只是通过额外的代码更容易实现这个

class Member
  has_many :snacks

  def find_snacks(snacktypes)
    snacks.red.snacktypefind(snacktypes)
  end

end

这变成了

"SELECT snacks.* FROM snacks WHERE snacks.member_id = YOUR_MEMBER_ID AND snacks.color = 'red' AND snacks.snacktype IN (YOUR snacktypes array)"

目前我们将其称为“查询和推送”的实施方式存在缺陷。

首先,这将创建可能由单个对象组成的多个微型集合。这将是迭代的地狱,因为你必须嵌套迭代来实际访问对象。 其次,这将为每个snacktype创建多个查询1,这将降低性能。

您真正想要的是链接查询方法,将所有内容缩小到只包含您需要的元素的ActiveRecord::Relation。这将执行单个查询,当您迭代管道对象时,将是您要访问的实际对象,而不是另一个必须再次迭代的ActiveRecord::Relation

ActiveRecord Query Methods关于范围和查询链的重要部分是它们在链完成之前不会被执行,从而允许您以非常精细的方式轻松添加和删除条件。这样,您可以显式地定位数据库中的数据,而不是将其加载到内存中并从那里清除它。

答案 1 :(得分:0)

我最终这样做了:

 def find_snacks(snacktypes)
  returnarray = self.snacks.none

  snacktypes.each do |snacktype|
   returnarray += self.snacks.red.snacktypefind(snacktype)
 end
 return returnarray
end

由于 .none ,仅适用于rails 4,但我没有rails 3项目,所以我认为没关系。