我有一个循环,它击中几个作用域,然后将结果推入一个数组。我遇到的问题是,如果没有与范围匹配的记录,它仍然会返回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 []>]
这次我做错了什么傻事?再次感谢您的帮助!
哇,你用额外的代码让它变得更容易了,这个怎么样
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查询方法作用域和查询链的重要之处在于,在链完成之前,它们不会被执行,这允许您以非常精细的方式轻松地添加和删除条件。通过这种方式,您可以明确地将数据库中的数据作为目标,而不是将其加载到内存中并从内存中清除。
我最终做了这个:
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项目,所以我认为这还可以。