Question

I want to export a csv file from Rails and I'm following the Railscast on this topic (http://railscasts.com/episodes/362-exporting-csv-and-excel?view=asciicast).

In the Railscast, the controller (products_controller.rb) contains:

    def index
      @products = Product.order(:name)
      respond_to do |format|
        format.html
        format.csv { send_data @products.to_csv }
      end
    end

The Product model (models/product.rb) contains:

    def self.to_csv
      CSV.generate do |csv|
        csv << column_names
        all.each do |product|
          csv << product.attributes.values_at(*column_names)
        end
      end
    end

As seen in this StackOverflow question (Exporting CSV data from Rails), to_csv is a class method that is being called on an array of class objects. I expected this to fail because to_csv is not being called on the Product class.

This works, but why does it work?

Était-ce utile?

La solution

My question should have been "Why would sending the message, to_csv, to an instance of ActiveRecord::Relation cause a method on the Product class object to be invoked?"

In Rails, class methods automatically become available as "collection" methods; This is the reason why they are available to Relation objects (See this SO question/answer I missed earlier: how does this Ruby class method get invoked?).

Autres conseils

You are indeed correct - you are sending the message to_csv to an instance of, initially ActiveRecord::Relation, which ultimately is transformed into Array.

Have you required csv? If so, sending to_csv to an instance of an Array will work.

The stdlib/csv library decorates Array - http://ruby-doc.org/stdlib-1.9.3/libdoc/csv/rdoc/Array.html

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top