csv_rails 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|