2011-03-11 70 views
2

我们有一个模型协会,看起来是这样的:模型关联返回的数组不是数组?

class Example < ActiveRecord::Base 
    has_many :others, :order => 'others.rank' 
end 

的排名列是一个整数类型。这些特定模型的细节并不重要,但我们发现与其他模型之间的其他has_many关联存在同样的问题。

,我们还增加了可枚举模块:

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 

这增加,我们可以用它来从ActiveRecord对象的数组获取记录ID阵列的collect_id方法。

因此,如果我们使用普通的ActiveRecord的发现:所有的,我们得到一个不错的数组,我们就可以使用collect_id上,但如果我们用Example.others.collect_id,我们得到

NoMethodError: undefined method `collect_id' for #<Class:0x2aaaac0060a0> 

Example.others。类返回“Array”,所以它是撒谎还是困惑?

我们的解决方案迄今为止一直使用这种方式:

Example.others.to_a.collect_id 

这工作,但这个似乎有点陌生。你为什么要这样做?

我们关于Ruby 1.8.7和Rails 2.3.4

回答

5

模型关联是代理,而不仅仅是简单的数组。

而不是example.others.all.collect_id和你的补丁,我建议你使用example.others.all.map(&:id)这是标准的Rails和Ruby> = 1.8.7方法来收集单个属性。

0

您应该使用all

example.others.all.collect_id 
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

两个可能的解决方案:

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了解更多详情。在页面中搜索“关联扩展”以访问相关部分。

+0

啊,我在StackOverflow上学得太多了。这一定会派上用场。有些时候我想知道如何扩展两种模型之间的关联。惊人的辉煌...像'@ topic.comments.class'这样的东西从来没有给我关联对象的名字,它总是看到'。class',并在将类作为'Array'给予我之前转换为Array,即使我知道在您尝试对数据执行操作之前并不完全正确。 – nzifnab