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 +47 -3
- data/lib/csv_rails/active_record.rb +44 -0
- data/lib/csv_rails/array.rb +15 -11
- data/lib/csv_rails/version.rb +1 -1
- data/lib/csv_rails.rb +4 -3
- data/test/csv_rails/active_record_test.rb +91 -0
- data/test/csv_rails/array_test.rb +14 -0
- data/test/dummy/app/controllers/users_controller.rb +4 -4
- data/test/dummy/app/models/group.rb +4 -0
- data/test/dummy/app/models/membership.rb +4 -0
- data/test/dummy/app/models/user.rb +3 -0
- data/test/dummy/config/application.rb +1 -1
- data/test/dummy/config/locales/ja.yml +5 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20120328072253_create_groups.rb +13 -0
- data/test/dummy/db/migrate/20120328072740_create_memberships.rb +14 -0
- data/test/dummy/db/schema.rb +14 -1
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +1436 -0
- data/test/dummy/log/test.log +2322 -0
- data/test/dummy/test/fixtures/groups.yml +7 -0
- data/test/dummy/test/fixtures/memberships.yml +9 -0
- data/test/dummy/test/fixtures/users.yml +12 -5
- data/test/dummy/test/functional/users_controller_test.rb +5 -3
- data/test/dummy/test/unit/group_test.rb +8 -0
- data/test/dummy/test/unit/membership_test.rb +8 -0
- data/test/dummy/test/unit/user_test.rb +0 -67
- data/test/dummy/tmp/pids/server.pid +1 -0
- metadata +29 -8
- data/lib/active_record/acts/csv.rb +0 -42
- data/lib/tasks/csv_rails_tasks.rake +0 -4
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, :
|
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
|
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
|
data/lib/csv_rails/array.rb
CHANGED
@@ -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
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
27
|
+
_csv << element.to_csv_ary(fields, opts)
|
24
28
|
end
|
25
29
|
end
|
26
30
|
opts[:encoding] ? csv.encode(opts[:encoding]) : csv
|
data/lib/csv_rails/version.rb
CHANGED
data/lib/csv_rails.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
|
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], :
|
14
|
+
format.csv { render csv: @users, fields: [:id, :name, :age, :"groups.first.name"], encoding: 'SJIS' }
|
15
15
|
end
|
16
16
|
end
|
17
17
|
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
|
-
|
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"
|
Binary file
|
data/test/dummy/db/schema.rb
CHANGED
@@ -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 =>
|
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"
|
data/test/dummy/db/test.sqlite3
CHANGED
Binary file
|