Rails 3: How to respond_with csv without having a template file?

后端 未结 6 2361
时光取名叫无心
时光取名叫无心 2020-12-28 17:29

I have an object that has a to_csv method and I want to pass it to respond_with to render csv from my controller. My code looks like this:

6条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-28 18:03

    This is an old question but here's an updated method for the custom Renderer for newer versions of Rails (currently using 3.2.11 and Ruby 1.9.3) taken from the ActionController::Renderers documentation: http://api.rubyonrails.org/classes/ActionController/Renderers.html#method-c-add

    As florish said, create an initializer but add this code:

    ActionController::Renderers.add :csv do |obj, options|
      filename = options[:filename] || 'data'
      str = obj.respond_to?(:to_csv) ? obj.to_csv : obj.to_s
      send_data str, :type => Mime::CSV,
        :disposition => "attachment; filename=#{filename}.csv"
    end
    

    And use it as such:

    def show
      @csvable = Csvable.find(params[:id])
      respond_to do |format|
        format.html
        format.csv { render :csv => @csvable, :filename => @csvable.name }
      end
    end
    

    I take no credit for the code above, it's straight from the documentation, but this worked for me in Rails 3.2.11 so pointing it out for people coming across this thread for the first time.

    In my project I'm not using a to_csv method, I'm actually building the CSV manually first. So here's what mine looks like:

    def show
      items = Item.where(something: true)
      csv_string = CSV.generate do |csv|
        # header row
        csv << %w(id name)
        # add a row for each item
        items.each do |item|
          csv << [item.id, item.name]
        end
      end
      respond_to do |format|
        format.csv { render :csv => csv_string, :filename => "myfile.csv" }
      end
    end
    

    You should obvious move the CSV creation code to some other class or model but putting it here inline just to illustrate.

提交回复
热议问题