3

RailsアプリからのCSVのエクスポートに関するスクリーンキャストで、 RyanBatesは次の簡単なコードを提示しました。

クラスメソッドProduct::to_csvが実際にProductController.rbの5行目でどのように呼び出されるかを理解しようとしています。これは、通常の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()のようになると思います。

ドキュメントによると、@productsはActiveRecord::Relationのインスタンスです。ActiveRecord :: Relationshipのインスタンスに送信されたメッセージにより、Productクラスオブジェクトのメソッドが呼び出されるのはなぜですか?さらに奇妙なことに、送信者と受信者の両方でto_csvの名前を任意の名前に変更すると、NoMethodErrorが発生するため、to_で始まる名前に基づいて魔法がかかっている可能性があります。

明らかな何かが欠けていますか?どんな説明でも大歓迎です。

4

2 に答える 2

3

これは、Rails が行うことの 1 つにすぎません。すべてのクラス メソッドは自動的に「コレクション」メソッドとして使用できるようになります。つまり、関係オブジェクトで使用できるようになります。スコープとクラス メソッドは、そのように交換可能です。

于 2012-07-21T00:06:16.720 に答える
1

今のところ、次の質問に答えることができます。

ActiveRecord::Relation のインスタンスに送信されたメッセージによって、Product クラス オブジェクトのメソッドが呼び出されるのはなぜですか?

ActiveRecord::Relationクラスは、実際に複数の SQL クエリをトリガーすることなく、複数のメソッドをチェーンするために使用されます。このように書くProduct.where('price <= ?', 100).order(:price).limit(30)と、Rails はクエリを 1 つだけ実行します。

ActiveRecord::Relationデータにアクセスしようとするまで (たとえば、firstまたはall呼び出しにより)インスタンスが存在するため、魔法が機能しますActiveRecord::Base

簡単に言えば、クラスをチェックすると、が表示され@products.classますがActiveRecord::Relation、後でProductインスタンスがあり、to_csvメソッドを呼び出すことができます。

于 2012-07-20T22:59:11.940 に答える