在Rails 3.2模型中,希望创建一个"to_csv“类方法来从ActiveRecord作用域生成CSV输出,如下所示:
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...and来自User.first.posts.scoped的结果显式为ActiveRecord::Relation,我仍然按了数组方法。如果我将该方法重命名为类似于"to_csvx“的东西,它就会像预期的那样工作。
我希望有人能解释为什么ActiveRecord::Relation对象优先命中数组#to_csv方法,而不是to_csv类方法。虽然这个类方法(期望由AR作用域调用的类方法)似乎有道理,但我想知道整个想法是否存在固有的问题?
发布于 2013-04-15 21:25:04
好吧,回答我自己的问题太差劲了,但是基于@m_x和Railscast 239 http://railscasts.com/episodes/239-activerecord-relation-walkthrough的评论,我更深入到Rails源代码中.我可以看到,Relation 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“作用域”类方法命名为与数组实例方法相同的类方法,则关系将被转换为数组,而数组方法将被调用而不是类方法。
轻松解决方案:只需选择另一个方法名.
https://stackoverflow.com/questions/16020600
复制相似问题