= CsvRails CsvRails provides a simple way of download csv in Rails 3. == Supported versions Ruby 1.9 (1.8 not supported) Rails 3 ActiveRecord or Mongoid == Install To use CsvRails simply add the line gem 'csv_rails' to your Gemfile and then run bundle install == Example class UsersController < ApplicationController def index @users = User.all respond_to do |format| format.html { @users = @users.all } format.json { render json: @users } format.csv{ render csv: @users, fields: [:id, :name, :age], encoding: 'SJIS', without_header: true } end end == Usage === Download If you want formatted attribute, CsvRails call "#{attribute}_as_csv". For example, you wish formatted created_at then you write like this. class User < ActiveRecord::Base def created_at_as_csv created_at.strftime("%F %H:%M") end end CsvRails define a singleton method Array.to_csv, and the method accept fields option. The fields option can not only database fields also method and method chain. class User < ActiveRecord::Base has_many :memberships has_many :groups, through: :memberships def ok "OK" end end class UsersController < ApplicationController def index @users = User.all respond_to do |format| format.csv{ render csv: @users, fields: [:ok, :"groups.first.name"], encoding: 'SJIS' } end end If you do not use :header option, header is using :fields and I18n transfer. # config/locales/ja.yml ja: activerecord: attributes: group: &groupmodel name: グループ名 user: id: ID name: 名前 age: 年齢 ok: OK # rails3 groups: first: <<: *groupmodel # rails 3.2.3 - 3.2.5 user/groups: first: <<: *groupmodel # rails 3.2.6 or higher groups/first: <<: *groupmodel # app/controllers/user_controller.rb def index @users = User.where("id < 1").all respond_to do |format| format.csv{ render csv: @users, fields: [:ok, :"groups.first.name"], encoding: 'SJIS' } #=> "OK,グループ名" end end And you can use tsv. Both tsv and csv can accept row_sep option. # app/controllers/user_controller.rb def index @users = User.all respond_to do |format| format.csv{ render csv: @users, :row_sep => "\r\n" } format.tsv{ render tsv: @users, :row_sep => "\r\n" } end end You also use i18n_scope option # config/locales/ja.yml ja: csv: name: なまえ User.where("id < 1").all.to_csv(:i18n_scope => :csv) #=> "なまえ\n" === Upload CSVRails is also have upload concern. You should include CSVRails::Import into your model. example # app/model/user.rb class User < ActiveRecord::Base attr_accessor :file include CsvRails::Import .... And render file_field into form example # app/views/users/index.html.erb <%= form_for(@user, multipart: true) do |f| %> File: <%= f.file_field :file %> <%= f.submit 'Upload' %> <% end %> Next implement action # app/controllers/users_controller.rb def create if params[:format] == 'csv' users = User.csv_import(params[:file]) if users.find{|u| u.errors.any? } render :index else redirect_to users_path, notice: 'Upload success' end end end csv_import is be able to use block. User.csv_import(params[:file]) do |user, params, row_number| next false if row_number == 2 # 'next false' in the block, the line is skipped. end csv_import use transaction, if invalid line is existed then all rows is not imported. First line used for fields, but you can manually choose it using options User.csv_import(params[:file], fields: [:age, :name]) It line first line has 'id', csv_import call where(id: id).first_or_initialize, but you can use other field name User.csv_import(params[:file], find_key: :name) #=> It call User.where(name: name).first_or_initialize internal. Copyright (c) 2012-2013 yalab, released under the MIT license