如何调用这个Ruby类方法?
在使用rails应用程序导出CSV的屏幕上,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,所以也许根据以to_开头的名称进行一些神奇的冒险?
我错过了一些明显的东西吗 任何澄清将不胜感激。
这只是Rails所做的事情之一。 任何类方法都自动变为“集合”方法,这意味着它们可用于关系对象。 范围和类方法可以这种方式互换。
我现在可以回答以下问题:
为什么发送到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
实例,然后您可以调用to_csv
方法。