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 © 2012-2013 yalab, released under the MIT license