comma 0.3.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +0 -1
- data/MIT-LICENSE +1 -1
- data/README.rdoc +152 -98
- data/VERSION +1 -1
- data/comma.gemspec +70 -0
- data/lib/comma.rb +7 -6
- data/lib/comma/association_proxy.rb +6 -0
- data/lib/comma/extractors.rb +0 -1
- data/lib/comma/named_scope.rb +0 -1
- data/lib/comma/object.rb +3 -3
- data/lib/comma/render_as_csv.rb +34 -4
- data/spec/comma/comma_spec.rb +48 -41
- data/spec/comma/extractors_spec.rb +26 -26
- data/spec/spec.opts +1 -1
- data/spec/spec_helper.rb +9 -7
- metadata +39 -13
data/.gitignore
CHANGED
data/MIT-LICENSE
CHANGED
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
17
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
18
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
19
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
CHANGED
@@ -12,55 +12,61 @@ CSV can be a bit of a boring format - the motivation behind Comma was to have a
|
|
12
12
|
|
13
13
|
An example Comma CSV enabled ActiveRecord class:
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
15
|
+
class Book < ActiveRecord::Base
|
16
|
+
|
17
|
+
# ================
|
18
|
+
# = Associations =
|
19
|
+
# ================
|
20
|
+
has_many :pages
|
21
|
+
has_one :isbn
|
22
|
+
belongs_to :publisher
|
23
|
+
|
24
|
+
# ===============
|
25
|
+
# = CSV support =
|
26
|
+
# ===============
|
27
|
+
comma do
|
28
|
+
|
29
|
+
name
|
30
|
+
description
|
31
|
+
|
32
|
+
pages :size => 'Pages'
|
33
|
+
publisher :name
|
34
|
+
isbn :number_10 => 'ISBN-10', :number_13 => 'ISBN-13'
|
35
|
+
blurb 'Summary'
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
40
|
|
41
41
|
Annotated, the comma description is as follows:
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
43
|
+
# starts a Comma description block, generating 2 methods #to_comma and
|
44
|
+
# #to_comma_headers for this class.
|
45
|
+
comma do
|
46
|
+
|
47
|
+
# name, description are attributes of Book with the header being reflected as
|
48
|
+
# 'Name', 'Description'
|
49
|
+
name
|
50
|
+
description
|
51
|
+
|
52
|
+
# pages is an association returning an array, :size is called on the
|
53
|
+
# association results, with the header name specified as 'Pages'
|
54
|
+
pages :size => 'Pages'
|
55
|
+
|
56
|
+
# publisher is an association returning an object, :name is called on the
|
57
|
+
# associated object, with the reflected header 'Name'
|
58
|
+
publisher :name
|
59
|
+
|
60
|
+
# isbn is an association returning an object, :number_10 and :number_13 are
|
61
|
+
# called on the object with the specified headers 'ISBN-10' and 'ISBN-13'
|
62
|
+
isbn :number_10 => 'ISBN-10', :number_13 => 'ISBN-13'
|
63
|
+
|
64
|
+
# blurb is an attribute of Book, with the header being specified directly
|
65
|
+
# as 'Summary'
|
66
|
+
blurb 'Summary'
|
67
|
+
|
68
|
+
end
|
69
|
+
|
64
70
|
In the above example, any of the declarations (name, description, pages, publisher, isbn, blurb, etc), could be methods, attributes, associations, etc - no distinction during configuration is required, as everything is invoked via Ruby's #send method.
|
65
71
|
|
66
72
|
You can get the CSV representation of any object by calling the to_comma method, optionally providing a CSV description name to use.
|
@@ -69,85 +75,133 @@ Object values are automatically converted to strings via to_s allowing you to re
|
|
69
75
|
|
70
76
|
Multiple CSV descriptions can also be specified for the same class, eg:
|
71
77
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
78
|
+
class Book < ActiveRecord::Base
|
79
|
+
|
80
|
+
# ================
|
81
|
+
# = Associations =
|
82
|
+
# ================
|
83
|
+
has_many :pages
|
84
|
+
has_one :isbn
|
85
|
+
belongs_to :publisher
|
86
|
+
|
87
|
+
# ===============
|
88
|
+
# = CSV support =
|
89
|
+
# ===============
|
90
|
+
comma do
|
91
|
+
|
92
|
+
name
|
93
|
+
description
|
94
|
+
|
95
|
+
pages :size => 'Pages'
|
96
|
+
publisher :name
|
97
|
+
isbn :number_10 => 'ISBN-10', :number_13 => 'ISBN-13'
|
98
|
+
blurb 'Summary'
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
comma :brief do
|
103
|
+
|
104
|
+
name
|
105
|
+
description
|
106
|
+
blurb 'Summary'
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
106
112
|
You can specify which output format you would like to use via an optional parameter to to_comma:
|
107
113
|
|
108
|
-
|
114
|
+
Book.limited(10).to_comma(:brief)
|
109
115
|
|
110
116
|
Specifying no description name to to_comma is equivalent to specifying :default as the description name.
|
111
117
|
|
112
118
|
You can pass options for FasterCSV, e.g.
|
113
119
|
|
114
|
-
|
120
|
+
Book.limited(10).to_comma(:style => :brief,
|
121
|
+
:col_sep => ';',
|
122
|
+
:force_quotes => true)
|
115
123
|
|
116
124
|
You can pass the :filename option and have Comma writes the CSV output to this file:
|
117
125
|
|
118
|
-
|
126
|
+
Book.limited(10).to_comma(:filename => 'books.csv')
|
127
|
+
|
128
|
+
== Using blocks
|
129
|
+
|
130
|
+
For more complex relationships you can pass blocks for calculated values, or related values. Following the previous example here is a comma set using blocks (both with and without labels for your CSV headings):
|
131
|
+
|
132
|
+
class Publisher < ActiveRecord::Base
|
133
|
+
# ================
|
134
|
+
# = Associations =
|
135
|
+
# ================
|
136
|
+
has_one :primary_contact, :class_name => "User" #(basic user with a name)
|
137
|
+
has_many :users
|
138
|
+
end
|
139
|
+
|
140
|
+
class Book < ActiveRecord::Base
|
141
|
+
|
142
|
+
# ================
|
143
|
+
# = Associations =
|
144
|
+
# ================
|
145
|
+
has_many :pages
|
146
|
+
has_one :isbn
|
147
|
+
belongs_to :publisher
|
148
|
+
|
149
|
+
# ===============
|
150
|
+
# = CSV support =
|
151
|
+
# ===============
|
152
|
+
comma do
|
153
|
+
name
|
154
|
+
description
|
155
|
+
|
156
|
+
pages :size => 'Pages'
|
157
|
+
publisher :name
|
158
|
+
publisher { |publisher| publisher.primary_contact.name.to_s.titleize }
|
159
|
+
publisher 'Number of publisher users' do |publisher| publisher.users.size end
|
160
|
+
isbn :number_10 => 'ISBN-10', :number_13 => 'ISBN-13'
|
161
|
+
blurb 'Summary'
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
In the preceding example, the 2 new fields added (both based on the publisher relationship) mean that the following will be added:
|
169
|
+
- the first example 'publishers_contact' is loaded straight as a block. The value returned by the lambda is displayed with a header value of 'Publisher'
|
170
|
+
- the second example 'total_publishers_users' is sent via a hash and a custom label is set, if used in the first examples method the header would be 'Publisher', but sent as a hash the header is 'Number of publisher users'.
|
119
171
|
|
120
172
|
=== USING WITH RAILS
|
121
173
|
|
122
174
|
When used with Rails (ie. add 'comma' as a gem dependency), Comma automatically adds support for rendering CSV output in your controllers:
|
123
175
|
|
124
|
-
|
176
|
+
class BooksController < ApplicationController
|
177
|
+
|
178
|
+
def index
|
179
|
+
respond_to do |format|
|
180
|
+
format.csv { render :csv => Book.limited(50) }
|
181
|
+
end
|
182
|
+
end
|
125
183
|
|
126
|
-
|
127
|
-
respond_to do |format|
|
128
|
-
format.csv { render :csv => Book.limited(50) }
|
129
|
-
end
|
130
|
-
end
|
184
|
+
end
|
131
185
|
|
132
|
-
end
|
133
|
-
|
134
186
|
When used with Rails 2.3.*, Comma also adds support for exporting named scopes:
|
135
187
|
|
136
|
-
|
137
|
-
|
138
|
-
|
188
|
+
class Book < ActiveRecord::Base
|
189
|
+
named_scope :recent,
|
190
|
+
lambda { { :conditions => ['created_at > ?', 1.month.ago] } }
|
139
191
|
|
140
|
-
|
141
|
-
|
192
|
+
# ...
|
193
|
+
end
|
142
194
|
|
143
195
|
Calling the to_comma method on the named scope will internally use Rails' find_each method, instantiating only 1,000 ActiveRecord objects at a time:
|
144
196
|
|
145
|
-
|
197
|
+
Book.recent.to_comma
|
146
198
|
|
147
199
|
== DEPENDENCIES
|
148
200
|
|
149
201
|
If you're on Ruby 1.8.*, the FasterCSV gem is recommended for performance reasons.
|
150
202
|
|
151
|
-
|
203
|
+
gem install fastercsv
|
152
204
|
|
153
205
|
If you have any questions or suggestions for Comma, please feel free to contact me at crafterm@redartisan.com, all feedback welcome!
|
206
|
+
|
207
|
+
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/comma.gemspec
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{comma}
|
8
|
+
s.version = "0.4.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Marcus Crafter"]
|
12
|
+
s.date = %q{2010-10-19}
|
13
|
+
s.description = %q{Ruby Comma Seperated Values generation library}
|
14
|
+
s.email = %q{crafterm@redartisan.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".gitignore",
|
20
|
+
"MIT-LICENSE",
|
21
|
+
"README.rdoc",
|
22
|
+
"Rakefile",
|
23
|
+
"VERSION",
|
24
|
+
"comma.gemspec",
|
25
|
+
"init.rb",
|
26
|
+
"lib/comma.rb",
|
27
|
+
"lib/comma/array.rb",
|
28
|
+
"lib/comma/association_proxy.rb",
|
29
|
+
"lib/comma/extractors.rb",
|
30
|
+
"lib/comma/generator.rb",
|
31
|
+
"lib/comma/named_scope.rb",
|
32
|
+
"lib/comma/object.rb",
|
33
|
+
"lib/comma/render_as_csv.rb",
|
34
|
+
"spec/comma/ar_spec.rb",
|
35
|
+
"spec/comma/comma_spec.rb",
|
36
|
+
"spec/comma/extractors_spec.rb",
|
37
|
+
"spec/spec.opts",
|
38
|
+
"spec/spec_helper.rb",
|
39
|
+
"sudo"
|
40
|
+
]
|
41
|
+
s.homepage = %q{http://github.com/crafterm/comma}
|
42
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
43
|
+
s.require_paths = ["lib"]
|
44
|
+
s.rubyforge_project = %q{comma}
|
45
|
+
s.rubygems_version = %q{1.3.7}
|
46
|
+
s.summary = %q{Ruby Comma Seperated Values generation library}
|
47
|
+
s.test_files = [
|
48
|
+
"spec/comma/ar_spec.rb",
|
49
|
+
"spec/comma/comma_spec.rb",
|
50
|
+
"spec/comma/extractors_spec.rb",
|
51
|
+
"spec/spec_helper.rb"
|
52
|
+
]
|
53
|
+
|
54
|
+
if s.respond_to? :specification_version then
|
55
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
56
|
+
s.specification_version = 3
|
57
|
+
|
58
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
59
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
60
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 2.2.2"])
|
61
|
+
else
|
62
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
63
|
+
s.add_dependency(%q<activesupport>, [">= 2.2.2"])
|
64
|
+
end
|
65
|
+
else
|
66
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
67
|
+
s.add_dependency(%q<activesupport>, [">= 2.2.2"])
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
data/lib/comma.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
# conditional loading of activesupport
|
2
|
-
if defined? Rails and Rails.version
|
3
|
-
require 'activesupport'
|
4
|
-
else
|
2
|
+
if defined? Rails and (Rails.version.split('.').map(&:to_i) <=> [2,3,5]) < 0
|
3
|
+
require 'activesupport'
|
4
|
+
else
|
5
5
|
require 'active_support/core_ext/class/inheritable_attributes'
|
6
6
|
end
|
7
7
|
|
8
8
|
# load the right csv library
|
9
9
|
if RUBY_VERSION >= '1.9'
|
10
|
-
require 'csv'
|
10
|
+
require 'csv'
|
11
11
|
FasterCSV = CSV
|
12
|
-
else
|
12
|
+
else
|
13
13
|
begin
|
14
14
|
# try faster csv
|
15
15
|
require 'fastercsv'
|
16
|
-
rescue
|
16
|
+
rescue StandardError => e
|
17
17
|
if defined? Rails
|
18
18
|
Rails.logger.info "FasterCSV not installed, falling back on CSV"
|
19
19
|
else
|
@@ -32,6 +32,7 @@ require 'comma/render_as_csv'
|
|
32
32
|
|
33
33
|
if defined?(ActiveRecord)
|
34
34
|
require 'comma/named_scope'
|
35
|
+
require 'comma/association_proxy'
|
35
36
|
end
|
36
37
|
|
37
38
|
if defined?(ActionController)
|
@@ -0,0 +1,6 @@
|
|
1
|
+
class ActiveRecord::Associations::AssociationProxy
|
2
|
+
def to_comma(style = :default)
|
3
|
+
#Bug in Rails 2.3.5, this is a workaround as association_proxy.rb doesn't pass the &block in the send method so it silently fails
|
4
|
+
Comma::Generator.new(Array(self), style).run(:each)
|
5
|
+
end
|
6
|
+
end
|
data/lib/comma/extractors.rb
CHANGED
data/lib/comma/named_scope.rb
CHANGED
data/lib/comma/object.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
class Object
|
2
2
|
class_inheritable_accessor :comma_formats
|
3
|
-
|
3
|
+
|
4
4
|
def self.comma(style = :default, &block)
|
5
5
|
(self.comma_formats ||= {})[style] = block
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
def to_comma(style = :default)
|
9
9
|
raise "No comma format for class #{self.class} defined for style #{style}" unless self.comma_formats and self.comma_formats[style]
|
10
10
|
Comma::DataExtractor.new(self, &self.comma_formats[style]).results
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def to_comma_headers(style = :default)
|
14
14
|
raise "No comma format for class #{self.class} defined for style #{style}" unless self.comma_formats and self.comma_formats[style]
|
15
15
|
Comma::HeaderExtractor.new(self, &self.comma_formats[style]).results
|
data/lib/comma/render_as_csv.rb
CHANGED
@@ -4,9 +4,39 @@ module RenderAsCSV
|
|
4
4
|
end
|
5
5
|
|
6
6
|
def render_with_csv(options = nil, extra_options = {}, &block)
|
7
|
-
return render_without_csv(options, extra_options, &block) unless options.is_a?(Hash) and options[:csv]
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
return render_without_csv(options, extra_options, &block) unless options.is_a?(Hash) and options[:csv].present?
|
8
|
+
|
9
|
+
content = options.delete(:csv)
|
10
|
+
style = options.delete(:style) || :default
|
11
|
+
filename = options.delete(:filename)
|
12
|
+
|
13
|
+
headers.merge!(
|
14
|
+
'Content-Transfer-Encoding' => 'binary',
|
15
|
+
'Content-Type' => 'text/csv; charset=utf-8'
|
16
|
+
)
|
17
|
+
filename_header_value = "attachment"
|
18
|
+
filename_header_value += "; filename=\"#{filename}\"" if filename.present?
|
19
|
+
headers.merge!('Content-Disposition' => filename_header_value)
|
20
|
+
|
21
|
+
@performed_render = false
|
22
|
+
|
23
|
+
render_stream :status => 200,
|
24
|
+
:content => Array(content),
|
25
|
+
:style => style
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def render_stream(options)
|
31
|
+
status = options[:status]
|
32
|
+
content = options[:content]
|
33
|
+
style = options[:style]
|
34
|
+
|
35
|
+
render :status => status, :text => Proc.new { |response, output|
|
36
|
+
output.write FasterCSV.generate_line(content.first.to_comma_headers(style))
|
37
|
+
content.each { |line| output.write FasterCSV.generate_line(line.to_comma(style)) }
|
38
|
+
}
|
11
39
|
end
|
12
40
|
end
|
41
|
+
|
42
|
+
#credit : http://ramblingsonrails.com/download-a-large-amount-of-data-in-csv-from-rails
|
data/spec/comma/comma_spec.rb
CHANGED
@@ -1,31 +1,31 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
2
|
|
3
3
|
describe Comma do
|
4
|
-
|
4
|
+
|
5
5
|
it 'should extend object to add a comma method' do
|
6
6
|
Object.should respond_to(:comma)
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
it 'should extend object to have a to_comma method' do
|
10
10
|
Object.should respond_to(:to_comma)
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
it 'should extend object to have a to_comma_headers method' do
|
14
14
|
Object.should respond_to(:to_comma_headers)
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
end
|
18
18
|
|
19
19
|
describe Comma, 'generating CSV' do
|
20
|
-
|
20
|
+
|
21
21
|
before do
|
22
22
|
@isbn = Isbn.new('123123123', '321321321')
|
23
23
|
@book = Book.new('Smalltalk-80', 'Language and Implementation', @isbn)
|
24
|
-
|
24
|
+
|
25
25
|
@books = []
|
26
26
|
@books << @book
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
it 'should extend Array to add a #to_comma method which will return CSV content for objects within the array' do
|
30
30
|
@books.to_comma.should == "Title,Description,Issuer,ISBN-10,ISBN-13\nSmalltalk-80,Language and Implementation,ISBN,123123123,321321321\n"
|
31
31
|
end
|
@@ -69,30 +69,30 @@ describe Comma, 'generating CSV' do
|
|
69
69
|
end
|
70
70
|
|
71
71
|
describe Comma, 'defining CSV descriptions' do
|
72
|
-
|
72
|
+
|
73
73
|
describe 'with an unnamed description' do
|
74
|
-
|
74
|
+
|
75
75
|
before do
|
76
76
|
class Foo
|
77
77
|
comma do; end
|
78
|
-
end
|
78
|
+
end
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
it 'should name the current description :default if no name has been provided' do
|
82
82
|
Foo.comma_formats.should_not be_empty
|
83
83
|
Foo.comma_formats[:default].should_not be_nil
|
84
84
|
end
|
85
85
|
end
|
86
|
-
|
86
|
+
|
87
87
|
describe 'with a named description' do
|
88
|
-
|
88
|
+
|
89
89
|
before do
|
90
90
|
class Bar
|
91
91
|
comma do; end
|
92
92
|
comma :detailed do; end
|
93
|
-
end
|
93
|
+
end
|
94
94
|
end
|
95
|
-
|
95
|
+
|
96
96
|
it 'should use the provided name to index the comma format' do
|
97
97
|
Bar.comma_formats.should_not be_empty
|
98
98
|
Bar.comma_formats[:default].should_not be_nil
|
@@ -102,22 +102,22 @@ describe Comma, 'defining CSV descriptions' do
|
|
102
102
|
end
|
103
103
|
|
104
104
|
describe Comma, 'to_comma data/headers object extensions' do
|
105
|
-
|
105
|
+
|
106
106
|
describe 'with unnamed descriptions' do
|
107
|
-
|
107
|
+
|
108
108
|
before do
|
109
109
|
class Foo
|
110
110
|
attr_accessor :content
|
111
111
|
comma do; content; end
|
112
|
-
|
112
|
+
|
113
113
|
def initialize(content)
|
114
114
|
@content = content
|
115
115
|
end
|
116
116
|
end
|
117
|
-
|
117
|
+
|
118
118
|
@foo = Foo.new('content')
|
119
119
|
end
|
120
|
-
|
120
|
+
|
121
121
|
it 'should return and array of data content, using the :default CSV description if none requested' do
|
122
122
|
@foo.to_comma.should == %w(content)
|
123
123
|
end
|
@@ -125,28 +125,28 @@ describe Comma, 'to_comma data/headers object extensions' do
|
|
125
125
|
it 'should return and array of header content, using the :default CSV description if none requested' do
|
126
126
|
@foo.to_comma_headers.should == %w(Content)
|
127
127
|
end
|
128
|
-
|
128
|
+
|
129
129
|
it 'should return the CSV representation including header and content when called on an array' do
|
130
130
|
Array(@foo).to_comma.should == "Content\ncontent\n"
|
131
131
|
end
|
132
132
|
|
133
133
|
end
|
134
|
-
|
134
|
+
|
135
135
|
describe 'with named descriptions' do
|
136
|
-
|
136
|
+
|
137
137
|
before do
|
138
138
|
class Foo
|
139
139
|
attr_accessor :content
|
140
140
|
comma :detailed do; content; end
|
141
|
-
|
141
|
+
|
142
142
|
def initialize(content)
|
143
143
|
@content = content
|
144
144
|
end
|
145
145
|
end
|
146
|
-
|
146
|
+
|
147
147
|
@foo = Foo.new('content')
|
148
148
|
end
|
149
|
-
|
149
|
+
|
150
150
|
it 'should return and array of data content, using the :default CSV description if none requested' do
|
151
151
|
@foo.to_comma(:detailed).should == %w(content)
|
152
152
|
end
|
@@ -154,17 +154,17 @@ describe Comma, 'to_comma data/headers object extensions' do
|
|
154
154
|
it 'should return and array of header content, using the :default CSV description if none requested' do
|
155
155
|
@foo.to_comma_headers(:detailed).should == %w(Content)
|
156
156
|
end
|
157
|
-
|
157
|
+
|
158
158
|
it 'should return the CSV representation including header and content when called on an array' do
|
159
159
|
Array(@foo).to_comma(:detailed).should == "Content\ncontent\n"
|
160
160
|
end
|
161
|
-
|
161
|
+
|
162
162
|
it 'should raise an error if the requested description is not avaliable' do
|
163
163
|
lambda { @foo.to_comma(:bad) }.should raise_error
|
164
164
|
lambda { @foo.to_comma_headers(:bad) }.should raise_error
|
165
165
|
lambda { Array(@foo).to_comma(:bad) }.should raise_error
|
166
166
|
end
|
167
|
-
|
167
|
+
|
168
168
|
end
|
169
169
|
|
170
170
|
describe 'with block' do
|
@@ -172,39 +172,46 @@ describe Comma, 'to_comma data/headers object extensions' do
|
|
172
172
|
class Foo
|
173
173
|
attr_accessor :content, :created_at, :updated_at
|
174
174
|
comma do
|
175
|
-
time_to_s = lambda { |i| i && i.to_s(:db) }
|
176
175
|
content
|
177
176
|
content('Truncated Content') {|i| i && i.length > 10 ? i[0..10] : '---' }
|
178
|
-
created_at
|
179
|
-
updated_at
|
177
|
+
created_at { |i| i && i.to_s(:db) }
|
178
|
+
updated_at { |i| i && i.to_s(:db) }
|
179
|
+
created_at 'Created Custom Label' do |i| i && i.to_s(:short) end
|
180
|
+
updated_at 'Updated at Custom Label' do |i| i && i.to_s(:short) end
|
180
181
|
end
|
181
|
-
|
182
|
+
|
182
183
|
def initialize(content, created_at = Time.now, updated_at = Time.now)
|
183
184
|
@content = content
|
184
185
|
@created_at = created_at
|
185
186
|
@updated_at = updated_at
|
186
187
|
end
|
187
188
|
end
|
188
|
-
|
189
|
+
|
189
190
|
@time = Time.now
|
190
191
|
@content = 'content ' * 5
|
191
192
|
@foo = Foo.new @content, @time, @time
|
192
193
|
end
|
193
|
-
|
194
|
+
|
194
195
|
it 'should return yielded values by block' do
|
195
196
|
header, foo = Array(@foo).to_comma.split("\n")
|
196
|
-
foo.should == [@content, @content[0..10], @time.to_s(:db), @time.to_s(:db)].join(',')
|
197
|
+
foo.should == [@content, @content[0..10], @time.to_s(:db), @time.to_s(:db), @time.to_s(:short), @time.to_s(:short)].join(',')
|
197
198
|
end
|
198
|
-
|
199
|
+
|
200
|
+
it 'should return headers with custom labels from block' do
|
201
|
+
header, foo = Array(@foo).to_comma.split("\n")
|
202
|
+
header.should == ['Content', 'Truncated Content', 'Created at', 'Updated at', 'Created Custom Label', 'Updated at Custom Label'].join(',')
|
203
|
+
end
|
204
|
+
|
199
205
|
end
|
200
|
-
|
206
|
+
|
207
|
+
|
201
208
|
describe 'on an object with no comma declaration' do
|
202
|
-
|
209
|
+
|
203
210
|
it 'should raise an error mentioning there is no comma description defined for that class' do
|
204
211
|
lambda { 'a string'.to_comma }.should raise_error('No comma format for class String defined for style default')
|
205
212
|
lambda { 'a string'.to_comma_headers }.should raise_error('No comma format for class String defined for style default')
|
206
213
|
end
|
207
|
-
|
214
|
+
|
208
215
|
end
|
209
|
-
|
216
|
+
|
210
217
|
end
|
@@ -3,89 +3,89 @@ require File.dirname(__FILE__) + '/../spec_helper'
|
|
3
3
|
# comma do
|
4
4
|
# name 'Title'
|
5
5
|
# description
|
6
|
-
#
|
6
|
+
#
|
7
7
|
# isbn :number_10 => 'ISBN-10', :number_13 => 'ISBN-13'
|
8
8
|
# end
|
9
9
|
|
10
10
|
describe Comma::HeaderExtractor do
|
11
|
-
|
11
|
+
|
12
12
|
before do
|
13
13
|
@isbn = Isbn.new('123123123', '321321321')
|
14
14
|
@book = Book.new('Smalltalk-80', 'Language and Implementation', @isbn)
|
15
|
-
|
15
|
+
|
16
16
|
@headers = @book.to_comma_headers
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
describe 'when no parameters are provided' do
|
20
|
-
|
20
|
+
|
21
21
|
it 'should use the method name as the header name, humanized' do
|
22
22
|
@headers.should include('Description')
|
23
23
|
end
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
describe 'when given a string description as a parameter' do
|
27
|
-
|
27
|
+
|
28
28
|
it 'should use the string value, unmodified' do
|
29
29
|
@headers.should include('Title')
|
30
30
|
end
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
describe 'when an hash is passed as a parameter' do
|
34
|
-
|
34
|
+
|
35
35
|
describe 'with a string value' do
|
36
|
-
|
36
|
+
|
37
37
|
it 'should use the string value, unmodified' do
|
38
38
|
@headers.should include('ISBN-10')
|
39
39
|
end
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
describe 'with a non-string value' do
|
43
|
-
|
43
|
+
|
44
44
|
it 'should use the non string value converted to a string, humanized' do
|
45
45
|
@headers.should include('Issuer')
|
46
46
|
end
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
end
|
52
52
|
|
53
53
|
describe Comma::DataExtractor do
|
54
|
-
|
54
|
+
|
55
55
|
before do
|
56
56
|
@isbn = Isbn.new('123123123', '321321321')
|
57
57
|
@book = Book.new('Smalltalk-80', 'Language and Implementation', @isbn)
|
58
|
-
|
58
|
+
|
59
59
|
@data = @book.to_comma
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
describe 'when no parameters are provided' do
|
63
|
-
|
63
|
+
|
64
64
|
it 'should use the string value returned by sending the method name on the object' do
|
65
65
|
@data.should include('Language and Implementation')
|
66
66
|
end
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
describe 'when given a string description as a parameter' do
|
70
|
-
|
70
|
+
|
71
71
|
it 'should use the string value returned by sending the method name on the object' do
|
72
72
|
@data.should include('Smalltalk-80')
|
73
73
|
end
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
describe 'when an hash is passed as a parameter' do
|
77
|
-
|
77
|
+
|
78
78
|
describe 'with a string value' do
|
79
|
-
|
79
|
+
|
80
80
|
it 'should use the string value, returned by sending the hash key to the object' do
|
81
81
|
@data.should include('123123123')
|
82
82
|
@data.should include('321321321')
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
it 'should not fail when an associated object is nil' do
|
86
86
|
lambda { Book.new('Smalltalk-80', 'Language and Implementation', nil).to_comma }.should_not raise_error
|
87
87
|
end
|
88
88
|
end
|
89
89
|
end
|
90
|
-
|
91
|
-
end
|
90
|
+
|
91
|
+
end
|
data/spec/spec.opts
CHANGED
@@ -1 +1 @@
|
|
1
|
-
--colour
|
1
|
+
--colour
|
data/spec/spec_helper.rb
CHANGED
@@ -1,27 +1,29 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'spec'
|
3
|
-
require '
|
3
|
+
require 'activerecord'
|
4
|
+
ActiveRecord::ActiveRecordError # http://tinyurl.com/24f84gf
|
4
5
|
|
5
6
|
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
7
|
+
|
6
8
|
require 'comma'
|
7
9
|
|
8
10
|
|
9
11
|
class Book
|
10
12
|
attr_accessor :name, :description, :isbn
|
11
|
-
|
13
|
+
|
12
14
|
def initialize(name, description, isbn)
|
13
15
|
@name, @description, @isbn = name, description, isbn
|
14
16
|
end
|
15
|
-
|
17
|
+
|
16
18
|
comma do
|
17
19
|
name 'Title'
|
18
20
|
description
|
19
|
-
|
21
|
+
|
20
22
|
isbn :authority => :issuer
|
21
23
|
isbn :number_10 => 'ISBN-10'
|
22
24
|
isbn :number_13 => 'ISBN-13'
|
23
25
|
end
|
24
|
-
|
26
|
+
|
25
27
|
comma :brief do
|
26
28
|
name
|
27
29
|
description
|
@@ -30,10 +32,10 @@ end
|
|
30
32
|
|
31
33
|
class Isbn
|
32
34
|
attr_accessor :number_10, :number_13
|
33
|
-
|
35
|
+
|
34
36
|
def initialize(isbn_10, isbn_13)
|
35
37
|
@number_10, @number_13 = isbn_10, isbn_13
|
36
38
|
end
|
37
|
-
|
39
|
+
|
38
40
|
def authority; 'ISBN'; end
|
39
41
|
end
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: comma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 15
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
version: 0.4.0
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Marcus Crafter
|
@@ -9,29 +15,41 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date: 2010-
|
18
|
+
date: 2010-10-19 00:00:00 +11:00
|
13
19
|
default_executable:
|
14
20
|
dependencies:
|
15
21
|
- !ruby/object:Gem::Dependency
|
16
22
|
name: rspec
|
17
|
-
|
18
|
-
|
19
|
-
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
20
26
|
requirements:
|
21
27
|
- - ">="
|
22
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 13
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 2
|
33
|
+
- 9
|
23
34
|
version: 1.2.9
|
24
|
-
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id001
|
25
37
|
- !ruby/object:Gem::Dependency
|
26
38
|
name: activesupport
|
27
|
-
|
28
|
-
|
29
|
-
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
30
42
|
requirements:
|
31
43
|
- - ">="
|
32
44
|
- !ruby/object:Gem::Version
|
45
|
+
hash: 3
|
46
|
+
segments:
|
47
|
+
- 2
|
48
|
+
- 2
|
49
|
+
- 2
|
33
50
|
version: 2.2.2
|
34
|
-
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
35
53
|
description: Ruby Comma Seperated Values generation library
|
36
54
|
email: crafterm@redartisan.com
|
37
55
|
executables: []
|
@@ -46,9 +64,11 @@ files:
|
|
46
64
|
- README.rdoc
|
47
65
|
- Rakefile
|
48
66
|
- VERSION
|
67
|
+
- comma.gemspec
|
49
68
|
- init.rb
|
50
69
|
- lib/comma.rb
|
51
70
|
- lib/comma/array.rb
|
71
|
+
- lib/comma/association_proxy.rb
|
52
72
|
- lib/comma/extractors.rb
|
53
73
|
- lib/comma/generator.rb
|
54
74
|
- lib/comma/named_scope.rb
|
@@ -70,21 +90,27 @@ rdoc_options:
|
|
70
90
|
require_paths:
|
71
91
|
- lib
|
72
92
|
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
none: false
|
73
94
|
requirements:
|
74
95
|
- - ">="
|
75
96
|
- !ruby/object:Gem::Version
|
97
|
+
hash: 3
|
98
|
+
segments:
|
99
|
+
- 0
|
76
100
|
version: "0"
|
77
|
-
version:
|
78
101
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
none: false
|
79
103
|
requirements:
|
80
104
|
- - ">="
|
81
105
|
- !ruby/object:Gem::Version
|
106
|
+
hash: 3
|
107
|
+
segments:
|
108
|
+
- 0
|
82
109
|
version: "0"
|
83
|
-
version:
|
84
110
|
requirements: []
|
85
111
|
|
86
112
|
rubyforge_project: comma
|
87
|
-
rubygems_version: 1.3.
|
113
|
+
rubygems_version: 1.3.7
|
88
114
|
signing_key:
|
89
115
|
specification_version: 3
|
90
116
|
summary: Ruby Comma Seperated Values generation library
|