我们有一个看起来像这样的模型关联:
class Example < ActiveRecord::Base
has_many :others, :order => 'others.rank'
end
rank列是整数类型。这些特定模型的细节并不重要,因为我们发现其他模型之间的其他has_many关联存在同样的问题。
我们还添加了Enumerable模块:
module Enumerable
def method_missing(name)
super unless name.to_s[0..7] == 'collect_'
method = name.to_s[8..-1]
collect{|element| element.send(method)}
end
end
这会添加一个collect_id方法,我们可以使用它从ActiveRecord对象数组中获取记录ID数组。
因此,如果我们使用普通的ActiveRecord find:all,我们得到一个很好的数组,然后我们可以使用collect_id,但是如果我们使用Example.others.collect_id,我们得到
NoMethodError: undefined method `collect_id' for #<Class:0x2aaaac0060a0>
Example.others.class返回“数组”,所以是说谎还是混淆?
到目前为止,我们的解决方案是以这种方式使用它:
Example.others.to_a.collect_id
这有效,但这看起来有点奇怪。你为什么要那样做?
我们使用的是Ruby 1.8.7和Rails 2.3.4
答案 0 :(得分:5)
模型关联是代理,而不仅仅是简单的数组。
我建议您使用example.others.all.collect_id
而不是example.others.all.map(&:id)
和补丁,这是标准的Rails和Ruby&gt; = 1.8.7方式来收集单个属性。
答案 1 :(得分:3)
由于性能原因,ActiveRecord关联懒洋洋地加载has_many记录。例如,如果您调用example.others.count,则无需加载所有记录。尝试将此补丁与您的补丁一起添加到可枚举:
class ActiveRecord::Associations::AssociationCollection
def method_missing(name)
super unless name.to_s[0..7] == 'collect_'
load_target unless loaded?
method = name.to_s[8..-1]
@target.collect{|element| element.send(method)}
end
end
答案 2 :(得分:2)
两种可能的解决方案:
1)扩展特定关联:
class Example < ActiveRecord::Base
has_many :others, :order => 'others.rank' do
def method_missing(name)
super unless name.to_s[0..7] == 'collect_'
method = name.to_s[8..-1]
collect{|element| element.send(method)}
end
end
end
2)将扩展添加到模块以获得可重复的解决方案。
Rails提供了扩展关联数组的选项。
module Collector
def method_missing(name)
super unless name.to_s[0..7] == 'collect_'
method = name.to_s[8..-1]
collect{|element| element.send(method)}
end
end
class Example < ActiveRecord::Base
has_many :others, :order => 'others.rank', :extend => Collector
end
阅读documentation了解更多详情。在页面中搜索“Association Extensions”以进入相关部分。
答案 3 :(得分:0)
您应该使用all
example.others.all.collect_id