4

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?

2
  • I'm not sure what you mean. Self is your model, Product in your case. The method .to_csv is a class method. You call the method .to_csv on the class Product, what part seems odd to you? Commented Mar 26, 2014 at 16:46
  • Sorry, I didn't articulate my confusion very clearly. I was expecting something like Product.to_csv(@products) instead of @products.to_csv in the controller. Commented Mar 27, 2014 at 17:30

2 Answers 2

3

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?).

Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.