comma 0.3.2 → 0.4.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/.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
|