csv_rails 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -21,19 +21,63 @@ to your Gemfile and then run
21
21
  respond_to do |format|
22
22
  format.html { @users = @users.all }
23
23
  format.json { render json: @users }
24
- format.csv{ render csv: @users, :fields => [:id, :name, :age], :encoding => 'SJIS' }
24
+ format.csv{ render csv: @users, fields: [:id, :name, :age], encoding: 'SJIS', without_header: true }
25
25
  end
26
26
  end
27
27
 
28
28
 
29
29
  == Usage
30
30
 
31
- If you want formatted created_at in the csv you should write like this
31
+ If you want formatted attribute, CsvRails call "#{attribute}_as_csv". For example, you wish formatted created_at then you write like this.
32
32
 
33
33
  class User < ActiveRecord::Base
34
34
  def created_at_as_csv
35
35
  created_at.strftime("%F %H:%M")
36
36
  end
37
37
  end
38
-
38
+
39
+ 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.
40
+
41
+ class User < ActiveRecord::Base
42
+ has_many :memberships
43
+ has_many :groups, through: :memberships
44
+
45
+ def ok
46
+ "OK"
47
+ end
48
+ end
49
+
50
+ class UsersController < ApplicationController
51
+ def index
52
+ @users = User.all
53
+
54
+ respond_to do |format|
55
+ format.csv{ render csv: @users, fields: [:ok, :"groups.first.name"], encoding: 'SJIS' }
56
+ end
57
+ end
58
+
59
+ If you do not use :header option, header is using :fields and I18n transfer.
60
+ # config/locales/ja.yml
61
+ ja:
62
+ activerecord:
63
+ attributes:
64
+ group: &groupmodel
65
+ name: グループ名
66
+ user:
67
+ id: ID
68
+ name: 名前
69
+ age: 年齢
70
+ ok: OK
71
+ groups:
72
+ first:
73
+ <<: *groupmodel
74
+
75
+ # app/controllers/user_controller.rb
76
+ def index
77
+ @users = User.where("id < 1").all
78
+ respond_to do |format|
79
+ format.csv{ render csv: @users, fields: [:ok, :"groups.first.name"], encoding: 'SJIS' } #=> "OK,グループ名"
80
+ end
81
+ end
82
+
39
83
  Copyright (c) 2012 yalab, released under the MIT license
@@ -0,0 +1,44 @@
1
+ require 'csv'
2
+ module CsvRails
3
+ module ActiveRecord
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ ::ActiveRecord::Relation.send(:include, ClassMethods)
7
+ base.send(:include, InstanceMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+ def to_csv(opts={})
12
+ fields = if opts[:fields]
13
+ opts.delete(:fields)
14
+ elsif respond_to?(:attribute_names)
15
+ attribute_names
16
+ elsif self.is_a?(::ActiveRecord::Relation)
17
+ @klass.new.attribute_names
18
+ else
19
+ new.attribute_names
20
+ end
21
+ header = fields.map{|f| human_attribute_name(f) }
22
+ all.to_csv(opts.update(:fields => fields, :header => header))
23
+ end
24
+
25
+ def csv_header(names)
26
+ names.map{|n| human_attribute_name(n) }
27
+ end
28
+ end
29
+
30
+ module InstanceMethods
31
+ def to_csv_ary(fields=nil, opts={})
32
+ fields = attribute_names unless fields
33
+ fields.map{|field|
34
+ field.to_s.split(".").inject(self){|object, f|
35
+ next unless object
36
+ convert_method = "#{f}_as_csv"
37
+ method = respond_to?(convert_method) ? convert_method : f
38
+ object.send(f)
39
+ }
40
+ }
41
+ end
42
+ end
43
+ end
44
+ end
@@ -7,20 +7,24 @@ module CsvRails
7
7
  end
8
8
 
9
9
  module InstanceMethods
10
+ # ==== Options
11
+ # * <tt>:fields</tt> - target field names
12
+ # * <tt>:header</tt> - header
13
+ # * <tt>:without_header</tt> - total_count
14
+ # * <tt>:encoding</tt> - encoding
10
15
  def to_csv(opts={})
11
- return "" if length < 1
12
- first = self.first
13
- fields = opts.delete(:fields) || first.class.attribute_names
16
+ fields = opts[:fields]
17
+ header = if opts[:header]
18
+ opts.delete(:header)
19
+ elsif (klass = first.class).respond_to?(:csv_header)
20
+ klass.csv_header(fields)
21
+ else
22
+ fields
23
+ end
14
24
  csv = CSV.generate do |_csv|
15
- unless opts[:without_header]
16
- _csv << if first.class.respond_to?(:human_attribute_name)
17
- fields.map{|f| first.class.human_attribute_name(f) }
18
- else
19
- fields
20
- end
21
- end
25
+ _csv << header unless opts[:without_header]
22
26
  each do |element|
23
- _csv << element.to_csv_ary(fields, opts)
27
+ _csv << element.to_csv_ary(fields, opts)
24
28
  end
25
29
  end
26
30
  opts[:encoding] ? csv.encode(opts[:encoding]) : csv
@@ -1,3 +1,3 @@
1
1
  module CsvRails
2
- VERSION = "0.4.1"
2
+ VERSION = "0.5.0"
3
3
  end
data/lib/csv_rails.rb CHANGED
@@ -1,6 +1,7 @@
1
- require File.expand_path('../active_record/acts/csv', __FILE__)
2
- require File.expand_path('../csv_rails/array', __FILE__)
3
- ActiveRecord::Base.send(:include, ActiveRecord::Acts::Csv)
1
+ require 'csv_rails/array'
2
+ require 'csv_rails/active_record'
3
+
4
+ ActiveRecord::Base.send(:include, CsvRails::ActiveRecord)
4
5
  Array.send(:include, CsvRails::Array)
5
6
 
6
7
  ActionController::Renderers.add :csv do |obj, options|
@@ -0,0 +1,91 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'test_helper'
3
+ class CsvRails::ActiveRecordTest < ActiveSupport::TestCase
4
+ setup do
5
+ @user = User.create(:name => 'yalab', :age => '29', :secret => 'password')
6
+ @group = Group.create(:name => 'ruby')
7
+ @user.groups << @group
8
+ end
9
+
10
+ test "#to_csv_ary without params" do
11
+ assert_equal @user.attributes.length, @user.to_csv_ary.length
12
+ assert_equal @user.attributes.values[0..-2], @user.to_csv_ary[0..-2]
13
+ end
14
+
15
+ test "#to_csv_ary with field params" do
16
+ fields = [:name, :age]
17
+ assert_equal fields.map{|f| @user[f] }, @user.to_csv_ary(fields)
18
+ end
19
+
20
+ test "#to_csv_ary use method not a database field" do
21
+ assert_equal [@user.one], @user.to_csv_ary([:one])
22
+ end
23
+
24
+ test "#to_csv_ary can use association" do
25
+ assert_equal [@user.name, @group.name], @user.memberships.first.to_csv_ary([:"user.name", :"group.name"])
26
+ end
27
+
28
+ test "#to_csv_ary ignore empty association" do
29
+ name = 'noman'
30
+ assert_equal [name, nil], User.new(:name => 'noman').to_csv_ary([:name, :"groups.first.name"])
31
+ end
32
+
33
+ test "#updated_at_as_csv" do
34
+ assert_equal @user.updated_at.strftime("%F %H:%M"), @user.updated_at_as_csv
35
+ end
36
+
37
+ test ".to_csv without params" do
38
+ csv = CSV.parse(User.to_csv)
39
+ header = csv.first.map{|f| f.downcase.tr(' ', '_') }
40
+ header.delete("updated_at")
41
+ line = csv.last
42
+ header.each.with_index do |field, index|
43
+ assert_equal @user[field].to_s, line[index]
44
+ end
45
+ end
46
+
47
+ test ".to_csv can use fields option" do
48
+ fields = [:id, :name]
49
+ row = CSV.parse(User.to_csv(:fields => fields)).last
50
+ assert_equal fields.map{|f| @user[f].to_s }, row
51
+ end
52
+
53
+ test ".to_csv without_header" do
54
+ fields = [:id, :name]
55
+ row = CSV.parse(User.to_csv(:fields => fields, :without_header => true)).first
56
+ assert_not_equal fields.map{|f| User.human_attribute_name(f) }, row
57
+ end
58
+
59
+ test ".to_csv header use human_attribute_name" do
60
+ fields = [:id, :name, :one]
61
+ header = CSV.parse(User.to_csv(:fields => fields)).first
62
+ assert_equal fields.map{|f| User.human_attribute_name(f) }, header
63
+ end
64
+
65
+ test ".to_csv with scoped" do
66
+ User.create(:name => 'atsushi', :age => 45, :secret => 'none')
67
+ assert_equal 1, CSV.parse(User.where("age > 39").to_csv(:without_header => true)).length
68
+ end
69
+
70
+ test ".to_csv accept encoding" do
71
+ I18n.locale = :ja
72
+ assert_equal "名前".encode('SJIS'), CSV.parse(User.to_csv(:fields => [:name], :encoding => 'SJIS')).first.first
73
+ I18n.locale = :en
74
+ end
75
+
76
+ test ".csv_header with association" do
77
+ I18n.locale = :ja
78
+ assert_equal [User.human_attribute_name(:name), Group.human_attribute_name(:name)], User.csv_header([:name, :"groups.first.name"])
79
+ I18n.locale = :en
80
+ end
81
+
82
+ test ".to_csv with association" do
83
+ I18n.locale = :ja
84
+ csv =<<-EOS.gsub(/^\s+/, '')
85
+ #{User.human_attribute_name(:name)},#{Group.human_attribute_name(:name)}
86
+ #{@user.name},#{@group.name}
87
+ EOS
88
+ assert_equal csv, User.includes(:groups).to_csv(:fields => [:name, :"groups.first.name"])
89
+ I18n.locale = :en
90
+ end
91
+ end
@@ -0,0 +1,14 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'test_helper'
3
+
4
+ class CsvRails::ArrayTest < ActiveSupport::TestCase
5
+ test ".to_csv with header option" do
6
+ header = ['foo', 'bar']
7
+ assert_equal header.join(','), [].to_csv(:header => header).chomp
8
+ end
9
+
10
+ test ".to_csv accept encoding" do
11
+ name = "名前"
12
+ assert_equal name.encode('SJIS'), [].to_csv(:header => [name], :encoding => 'SJIS').chomp
13
+ end
14
+ end
@@ -1,17 +1,17 @@
1
1
  class UsersController < ApplicationController
2
2
  def index
3
- @users = User
3
+ @users = User.includes(:groups)
4
4
  respond_to do |format|
5
5
  format.html
6
- format.csv { render csv: @users, fields: [:id, :name, :age] }
6
+ format.csv { render csv: @users, fields: [:id, :name, :age, :"groups.first.name"], without_header: true }
7
7
  end
8
8
  end
9
9
 
10
10
  def sjis
11
- @users = User.all
11
+ @users = User.includes(:groups).all
12
12
  respond_to do |format|
13
13
  format.html
14
- format.csv { render csv: @users, fields: [:id, :name, :age], :encoding => 'SJIS'}
14
+ format.csv { render csv: @users, fields: [:id, :name, :age, :"groups.first.name"], encoding: 'SJIS' }
15
15
  end
16
16
  end
17
17
  end
@@ -0,0 +1,4 @@
1
+ class Group < ActiveRecord::Base
2
+ has_many :memberships
3
+ has_many :users, through: :memberships
4
+ end
@@ -0,0 +1,4 @@
1
+ class Membership < ActiveRecord::Base
2
+ belongs_to :user
3
+ belongs_to :group
4
+ end
@@ -1,4 +1,7 @@
1
1
  class User < ActiveRecord::Base
2
+ has_many :memberships
3
+ has_many :groups, through: :memberships
4
+
2
5
  def updated_at_as_csv
3
6
  self.updated_at.strftime("%F %H:%M")
4
7
  end
@@ -27,7 +27,7 @@ module Dummy
27
27
 
28
28
  # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
29
29
  # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
30
- # config.i18n.default_locale = :de
30
+ config.i18n.default_locale = :ja
31
31
 
32
32
  # Configure the default encoding used in templates for Ruby 1.9.
33
33
  config.encoding = "utf-8"
@@ -1,7 +1,12 @@
1
1
  ja:
2
2
  activerecord:
3
3
  attributes:
4
+ group: &groupmodel
5
+ name: グループ名
4
6
  user:
5
7
  id: ID
6
8
  name: 名前
7
9
  age: 年齢
10
+ groups:
11
+ first:
12
+ <<: *groupmodel
Binary file
@@ -0,0 +1,13 @@
1
+ class CreateGroups < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :groups do |t|
4
+ t.string :name
5
+
6
+ t.timestamps
7
+ end
8
+ end
9
+
10
+ def self.down
11
+ drop_table :groups
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ class CreateMemberships < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :memberships do |t|
4
+ t.references :user
5
+ t.references :group
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+
11
+ def self.down
12
+ drop_table :memberships
13
+ end
14
+ end
@@ -11,7 +11,20 @@
11
11
  #
12
12
  # It's strongly recommended to check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(:version => 20120323112247) do
14
+ ActiveRecord::Schema.define(:version => 20120328072740) do
15
+
16
+ create_table "groups", :force => true do |t|
17
+ t.string "name"
18
+ t.datetime "created_at"
19
+ t.datetime "updated_at"
20
+ end
21
+
22
+ create_table "memberships", :force => true do |t|
23
+ t.integer "user_id"
24
+ t.integer "group_id"
25
+ t.datetime "created_at"
26
+ t.datetime "updated_at"
27
+ end
15
28
 
16
29
  create_table "users", :force => true do |t|
17
30
  t.string "name"
Binary file