2013-04-15 36 views
0

在Rails 3.2的模式,希望打造一個「to_csv」類方法來生成一個ActiveRecord範圍CSV輸出,就像這樣:的ActiveRecord ::關係命中我的類方法的陣列方法,而不是

class Post 
    # ... 
    def self.to_csv(options = {}) 
    CSV.generate(options) do |csv| 
     scoped.each {|post| csv << record.attributes.values_at('title', 'text')} 
    end 
    end 
end 

我希望我可以用這樣的:

User.first.posts.to_csv 

但是,這種方法似乎是由陣列#to_csv方法被重寫。即使我這樣做:

User.first.posts.scoped.to_csv 

...從User.first.posts.scoped結果是明確一個ActiveRecord ::關係,我還是打了陣方法。如果我將這個方法重命名爲「to_csvx」,它就像預期的那樣工作。

我希望有人可以解釋如何/爲什麼的ActiveRecord :: Relation對象優先打陣列#to_csv方法而不是to_csv類方法。雖然這個(一個類方法期望被AR範圍調用)似乎是合理的,但我想知道整個想法是否存在固有的問題?

+0

從表面上看,這看起來類似於http://stackoverflow.com/questions/224128/how-do-you-make-a-method-apply-to-a-collection-of-activerecord-objects,但是這個問題的實際點是我能得到我需要通過這個鏈接在關係鏈的末端,而不是在將它們作爲參數傳遞給隱蔽的記錄。 –

+1

我只是猜測這裏:你'陣列#to_csv'方法似乎來自寶石/猴子補丁(據我所知它不是來自鐵軌本身)。以委託'to_csv'到'to_a'(見的ActiveRecord ::代表團(https://github.com/rails/rails/blob/master/activerecord/lib/active_record也許這也是創業板的補丁猴子'Relation' /relation/delegation.rb))。它會解釋你的問題,以及爲什麼使用另一個方法名稱。 –

+0

我應該注意的Ruby版本(1.9.3) to_csv法陣如下所示:http://apidock.com/ruby/Array/to_csv –

回答

4

OK,超級跛腳回答自己的問題,而是基於來自@m_x和Railscast 239 http://railscasts.com/episodes/239-activerecord-relation-walkthrough評論我深入到Rails的源代碼,我可以看到關聯respond_to榮譽,並method_missing喜歡的陣列方法到任何其他未明確定義爲關係的方法。

# from rails/active_record/relation/delegation.rb 

def respond_to?(method, include_private = false) 
    super || Array.method_defined?(method) || 
    @klass.respond_to?(method, include_private) || 
    arel.respond_to?(method, include_private) 
end 

protected 

def method_missing(method, *args, &block) 
    if Array.method_defined?(method) 
    ::ActiveRecord::Delegation.delegate method, :to => :to_a 
    to_a.send(method, *args, &block) 
    elsif @klass.respond_to?(method) 
    ::ActiveRecord::Delegation.delegate_to_scoped_klass(method) 
    scoping { @klass.send(method, *args, &block) } 
    elsif arel.respond_to?(method) 
    ::ActiveRecord::Delegation.delegate method, :to => :arel 
    arel.send(method, *args, &block) 
    else 
    super 
    end 
end 

所以,如果你的名字一個ActiveRecord「作用域」類方法一樣Array實例方法,關係將轉換爲一個數組,陣列方法將被調用,而不是你的類方法。

簡單的解決方法:只選擇另一種方法名。

+2

回答你自己的問題並不是跛腳,事實上,你甚至應該接受它。爲SO做出貢獻,並幫助人們...挖掘源頭。我覺得奇怪的是數組方法比關係方法更受歡迎,也許你應該在github上建議一個補丁 –

相關問題