在Exporting CSV from a rails app的广告投放中,Ryan Bates提供了以下简单代码。
我正在试图弄清楚如何在ProductController.rb的第5行调用类方法Product :: to_csv,因为它似乎不遵循正常的Ruby规则。
product.rb
1 class Product < ActiveRecord::Base
2 def self.to_csv(options = {})
3 ...
4 end
5 end
products_controller.rb
1 class ProductsController < ApplicationController
2 def index
3 @products = Product.order(:name)
4 respond_to do |format|
5 format.csv { send_data @products.to_csv }
6 ...
7 end
8 end
9 end
由于to_csv是一个类方法,我希望调用看起来像Product :: to_csv()。
根据文档,@ product是ActiveRecord :: Relation的一个实例。为什么发送到ActiveRecord :: Relation实例的消息会导致调用Product类对象的方法?为了使它更奇怪,在发送者和接收者中将to_csv重命名为某个任意名称会导致NoMethodError,所以也许根据以_开头的名字进行一些魔术?
我错过了一些明显的东西吗?任何澄清将不胜感激。
答案 0 :(得分:2)
这只是Rails所做的事情之一。任何类方法都自动变为“集合”方法,这意味着它们可用于关系对象。范围和类方法可以这种方式互换。
答案 1 :(得分:1)
我现在可以回答以下问题:
为什么将消息发送到ActiveRecord :: Relation的实例 导致调用Product类对象的方法?
ActiveRecord::Relation
类用于链接多个方法,而不会实际触发多个SQL查询。通过这种方式,您可以编写类似Product.where('price <= ?', 100).order(:price).limit(30)
的内容,而Rails只执行一个查询。
魔法有效,因为你有一个ActiveRecord::Relation
实例,直到你试图访问数据(例如因为first
或all
调用),那时查询将会运行,你将有ActiveRecord::Base
或他的一个后代。
长话短说,如果您使用@products.class
查看课程,您会看到ActiveRecord::Relation
,但稍后您有Product
个实例,然后您可以拨打{{1}方法。