make_exportable 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +43 -0
- data/VERSION +1 -1
- data/lib/make_exportable/core.rb +108 -107
- metadata +5 -4
data/Gemfile.lock
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
actionmailer (2.3.6)
|
5
|
+
actionpack (= 2.3.6)
|
6
|
+
actionpack (2.3.6)
|
7
|
+
activesupport (= 2.3.6)
|
8
|
+
rack (~> 1.1.0)
|
9
|
+
activerecord (2.3.6)
|
10
|
+
activesupport (= 2.3.6)
|
11
|
+
activeresource (2.3.6)
|
12
|
+
activesupport (= 2.3.6)
|
13
|
+
activesupport (2.3.6)
|
14
|
+
gemcutter (0.5.0)
|
15
|
+
json_pure
|
16
|
+
git (1.2.5)
|
17
|
+
jeweler (1.4.0)
|
18
|
+
gemcutter (>= 0.1.0)
|
19
|
+
git (>= 1.2.5)
|
20
|
+
rubyforge (>= 2.0.0)
|
21
|
+
json_pure (1.4.3)
|
22
|
+
rack (1.1.0)
|
23
|
+
rails (2.3.6)
|
24
|
+
actionmailer (= 2.3.6)
|
25
|
+
actionpack (= 2.3.6)
|
26
|
+
activerecord (= 2.3.6)
|
27
|
+
activeresource (= 2.3.6)
|
28
|
+
activesupport (= 2.3.6)
|
29
|
+
rake (>= 0.8.3)
|
30
|
+
rake (0.8.7)
|
31
|
+
rspec (1.3.0)
|
32
|
+
rubyforge (2.0.4)
|
33
|
+
json_pure (>= 1.1.7)
|
34
|
+
sqlite3-ruby (1.3.0)
|
35
|
+
|
36
|
+
PLATFORMS
|
37
|
+
ruby
|
38
|
+
|
39
|
+
DEPENDENCIES
|
40
|
+
jeweler
|
41
|
+
rails
|
42
|
+
rspec
|
43
|
+
sqlite3-ruby
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.2
|
data/lib/make_exportable/core.rb
CHANGED
@@ -22,117 +22,118 @@ module MakeExportable #:nodoc:
|
|
22
22
|
|
23
23
|
protected
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
# remove any invalid options
|
67
|
-
valid_options = [:as, :only, :except, :scopes, :conditions, :order, :include,
|
68
|
-
:group, :having, :limit, :offset, :joins]
|
69
|
-
options.slice!(*valid_options)
|
70
|
-
|
71
|
-
# Determine the exportable formats, default to all registered formats
|
72
|
-
options[:formats] = MakeExportable.exportable_formats.keys
|
73
|
-
if format_options = options.delete(:as)
|
74
|
-
options[:formats] = options[:formats] & Array.wrap(format_options).map(&:to_sym)
|
75
|
-
end
|
76
|
-
# Handle case when :as option was sent, but with no valid formats
|
77
|
-
if options[:formats].blank?
|
78
|
-
valid_formats = MakeExportable.exportable_formats.keys.map {|f| ":#{f}"}
|
79
|
-
raise MakeExportable::FormatNotFound.new("No valid export formats. Use: #{valid_formats.join(', ')}")
|
80
|
-
end
|
25
|
+
# <tt>make_exportable</tt> is an ActiveRecord method that, when called, add
|
26
|
+
# methods to a particular class to make exporting data from that class easier.
|
27
|
+
#
|
28
|
+
# Example:
|
29
|
+
#
|
30
|
+
# class Customer < ActiveRecord::Base
|
31
|
+
# make_exportable
|
32
|
+
# end
|
33
|
+
# Customer.to_export(:csv)
|
34
|
+
#
|
35
|
+
# An optional hash of options can be passed as an argument to establish the default
|
36
|
+
# export parameters.
|
37
|
+
#
|
38
|
+
# These options include:
|
39
|
+
# * :only and :except - specify columns or methods to export (defaults to all columns)
|
40
|
+
# * :as - specify formats to allow for exporting (defaults to all formats)
|
41
|
+
# * :scopes - specify scopes to be called on the class before exporting
|
42
|
+
# * find options - for Rails 2.3 and earlier compatibility, standard find options
|
43
|
+
# are supported (:conditions, :order, :limit, :offset, etc.). These will be deprecated
|
44
|
+
# and removed in future versions.
|
45
|
+
#
|
46
|
+
# Examples:
|
47
|
+
#
|
48
|
+
# class Customer < ActiveRecord::Base
|
49
|
+
# make_exportable :only => [:id, :username, :full_name]
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# class Customer < ActiveRecord::Base
|
53
|
+
# make_exportable :except => [:id, :password], :scopes => [:new_signups, :with_referals],
|
54
|
+
# :as => [:csv, :tsv, :xls]
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# class Customer < ActiveRecord::Base
|
58
|
+
# make_exportable :conditions => {:active => true}, :order => 'last_name ASC, first_name ASC',
|
59
|
+
# :as => [:json, :html, :xml]
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
def make_exportable(options={})
|
63
|
+
return unless self.table_exists?
|
64
|
+
# register the class as exportable
|
65
|
+
MakeExportable.exportable_classes[self.class_name] = self
|
81
66
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
options[:columns] = Array.wrap(only_options).map(&:to_sym)
|
87
|
-
end
|
88
|
-
if except_options = options.delete(:except)
|
89
|
-
options[:columns] = options[:columns] - Array.wrap(except_options).map(&:to_sym)
|
90
|
-
end
|
67
|
+
# remove any invalid options
|
68
|
+
valid_options = [:as, :only, :except, :scopes, :conditions, :order, :include,
|
69
|
+
:group, :having, :limit, :offset, :joins]
|
70
|
+
options.slice!(*valid_options)
|
91
71
|
|
92
|
-
|
72
|
+
# Determine the exportable formats, default to all registered formats
|
73
|
+
options[:formats] = MakeExportable.exportable_formats.keys
|
74
|
+
if format_options = options.delete(:as)
|
75
|
+
options[:formats] = options[:formats] & Array.wrap(format_options).map(&:to_sym)
|
76
|
+
end
|
77
|
+
# Handle case when :as option was sent, but with no valid formats
|
78
|
+
if options[:formats].blank?
|
79
|
+
valid_formats = MakeExportable.exportable_formats.keys.map {|f| ":#{f}"}
|
80
|
+
raise MakeExportable::FormatNotFound.new("No valid export formats. Use: #{valid_formats.join(', ')}")
|
81
|
+
end
|
93
82
|
|
94
|
-
|
95
|
-
|
96
|
-
|
83
|
+
# Determine the exportable columns, default to all columns and then
|
84
|
+
# remove columns using the :only and :except options
|
85
|
+
options[:columns] = column_names.map(&:to_sym)
|
86
|
+
if only_options = options.delete(:only)
|
87
|
+
options[:columns] = Array.wrap(only_options).map(&:to_sym)
|
88
|
+
end
|
89
|
+
if except_options = options.delete(:except)
|
90
|
+
options[:columns] = options[:columns] - Array.wrap(except_options).map(&:to_sym)
|
91
|
+
end
|
97
92
|
|
98
|
-
|
99
|
-
include MakeExportable::InstanceMethods
|
93
|
+
options[:scopes] ||= []
|
100
94
|
|
101
|
-
|
95
|
+
# exportable options will be :formats, :columns, :scopes & find options
|
96
|
+
write_inheritable_attribute :exportable_options, options
|
97
|
+
class_inheritable_reader :exportable_options
|
98
|
+
|
99
|
+
extend MakeExportable::ClassMethods
|
100
|
+
include MakeExportable::InstanceMethods
|
101
|
+
|
102
|
+
end
|
102
103
|
|
103
104
|
end
|
104
105
|
|
105
106
|
module ClassMethods
|
106
107
|
|
107
108
|
# <tt>exportable?<?tt> returns true if the class has called "make_exportable".
|
108
|
-
# This is overriding the default :exportable? in ActiveRecord::Base which
|
109
|
+
# This is overriding the default :exportable? in ActiveRecord::Base which
|
109
110
|
# always returns false.
|
110
|
-
# If a format is passed as an argument, returns true only if the format is
|
111
|
+
# If a format is passed as an argument, returns true only if the format is
|
111
112
|
# allowed for this class.
|
112
113
|
def exportable?(format=nil)
|
113
114
|
return exportable_options[:formats].include?(format.to_sym) if format
|
114
115
|
return true
|
115
116
|
end
|
116
117
|
|
117
|
-
# <tt>to_export</tt> exports records from a class. It can be called
|
118
|
+
# <tt>to_export</tt> exports records from a class. It can be called
|
118
119
|
# directly on an ActiveRecord class, but it can also be called on an ActiveRelation scope.
|
119
120
|
# It takes two arguments: a format (required) and a hash of options (optional).
|
120
121
|
#
|
121
122
|
# The options include:
|
122
123
|
# * :only and :except - specify columns or methods to export
|
123
124
|
# * :scopes - specify scopes to be called on the class before exporting
|
124
|
-
# * find options - for Rails 2.3 and earlier compatibility, standard find options
|
125
|
-
# are supported (:conditions, :order, :limit, :offset, etc.). These will be deprecated
|
125
|
+
# * find options - for Rails 2.3 and earlier compatibility, standard find options
|
126
|
+
# are supported (:conditions, :order, :limit, :offset, etc.). These will be deprecated
|
126
127
|
# and removed in future versions.
|
127
|
-
# * :headers - supply an array of custom headers for the columns of exported attributes,
|
128
|
+
# * :headers - supply an array of custom headers for the columns of exported attributes,
|
128
129
|
# the sizes of the header array and the exported columns must be equal.
|
129
|
-
#
|
130
|
+
#
|
130
131
|
# Examples:
|
131
132
|
#
|
132
|
-
# User.to_export(:xml, :only => [:first_name, :last_name, :username],
|
133
|
+
# User.to_export(:xml, :only => [:first_name, :last_name, :username],
|
133
134
|
# :order => 'users.last_name ASC')
|
134
135
|
#
|
135
|
-
# User.visible.sorted_by_username.to_export('csv',
|
136
|
+
# User.visible.sorted_by_username.to_export('csv',
|
136
137
|
# :only => [:first_name, :last_name, :username])
|
137
138
|
#
|
138
139
|
def to_export(format, options={})
|
@@ -144,16 +145,16 @@ module MakeExportable #:nodoc:
|
|
144
145
|
export_string = create_report(format, export_data, :headers => options[:headers])
|
145
146
|
return export_string
|
146
147
|
end
|
147
|
-
|
148
|
-
# <tt>get_export_data</tt> finds records for export using a combination of the default
|
149
|
-
# export options and the argument options, and returns an array of arrays representing
|
150
|
-
# the rows and columns of the export data. The first item ("row") in the array will be
|
148
|
+
|
149
|
+
# <tt>get_export_data</tt> finds records for export using a combination of the default
|
150
|
+
# export options and the argument options, and returns an array of arrays representing
|
151
|
+
# the rows and columns of the export data. The first item ("row") in the array will be
|
151
152
|
# an array of strings to be used as column headers.
|
152
|
-
# Valid options include :only, :except, :scopes and the standard find options.
|
153
|
+
# Valid options include :only, :except, :scopes and the standard find options.
|
153
154
|
# See <tt>to_export</tt> for more details on the options.
|
154
155
|
#
|
155
156
|
# Example:
|
156
|
-
#
|
157
|
+
#
|
157
158
|
# User.get_export_data(:only => [:first_name, :last_name, :username])
|
158
159
|
# # => [['first_name', 'last_name', 'username'], ['John', 'Doe', 'johndoe'], ['Joe', 'Smith', 'jsmith']] }
|
159
160
|
#
|
@@ -164,23 +165,23 @@ module MakeExportable #:nodoc:
|
|
164
165
|
return export_data
|
165
166
|
end
|
166
167
|
|
167
|
-
# <tt>create_report</tt> creates a report from a set of data. It takes three arguments:
|
168
|
-
# a format, the data set to use for the report, and an optional hash of options.
|
169
|
-
# The only meaningful option is :headers which sets the strings to be used as column
|
168
|
+
# <tt>create_report</tt> creates a report from a set of data. It takes three arguments:
|
169
|
+
# a format, the data set to use for the report, and an optional hash of options.
|
170
|
+
# The only meaningful option is :headers which sets the strings to be used as column
|
170
171
|
# headers for the data set. The value of :headers can be:
|
171
172
|
# * true - headers are the first row in the data set
|
172
173
|
# * false - headers are not in the data set and should not be added
|
173
174
|
# * array of strings to use for the column headers
|
174
|
-
#
|
175
|
+
#
|
175
176
|
# The length of the headers must match the length of each row in the data set.
|
176
177
|
def create_report(format, data_set, options={})
|
177
178
|
if options[:headers] === true
|
178
179
|
options[:headers] = data_set.shift
|
179
180
|
end
|
180
|
-
|
181
|
+
|
181
182
|
validate_export_format(format)
|
182
183
|
validate_export_data_lengths(data_set, options[:headers])
|
183
|
-
|
184
|
+
|
184
185
|
format_class = MakeExportable.exportable_formats[format.to_sym]
|
185
186
|
formater = format_class.new(data_set, options[:headers])
|
186
187
|
return formater.generate, formater.mime_type
|
@@ -188,7 +189,7 @@ module MakeExportable #:nodoc:
|
|
188
189
|
|
189
190
|
private
|
190
191
|
|
191
|
-
# <tt>method_missing</tt> allows the class to accept dynamically named methods
|
192
|
+
# <tt>method_missing</tt> allows the class to accept dynamically named methods
|
192
193
|
# such as: SomeClass.to_xls_export(), SomeClass.create_csv_report()
|
193
194
|
def method_missing(method_id, *arguments)
|
194
195
|
possible_formats = MakeExportable.exportable_formats.keys.map(&:to_s).join('|')
|
@@ -205,11 +206,11 @@ module MakeExportable #:nodoc:
|
|
205
206
|
|
206
207
|
# <tt>find_export_data</tt> finds all objects of a given
|
207
208
|
# class using a combination of the default export options and the options passed in.
|
208
|
-
# Valid options include :scopes and the standard find options. It returns a collection of
|
209
|
+
# Valid options include :scopes and the standard find options. It returns a collection of
|
209
210
|
# objects matching the find criteria.
|
210
211
|
# See <tt>to_export</tt> for more details on the options.
|
211
212
|
def find_export_data(options={})
|
212
|
-
|
213
|
+
|
213
214
|
# merge with defaults then pull out the supported find and scope options
|
214
215
|
merged_options = options.reverse_merge(exportable_options)
|
215
216
|
find_options = merged_options.slice(:conditions, :order, :include, :group, :having, :limit, :offset, :joins)
|
@@ -230,12 +231,12 @@ module MakeExportable #:nodoc:
|
|
230
231
|
return collection
|
231
232
|
end
|
232
233
|
|
233
|
-
# <tt>map_export_data</tt> takes a collection and outputs an array of arrays representing
|
234
|
-
# the rows and columns of the export data. The first item ("row") in the array will be
|
234
|
+
# <tt>map_export_data</tt> takes a collection and outputs an array of arrays representing
|
235
|
+
# the rows and columns of the export data. The first item ("row") in the array will be
|
235
236
|
# an array of strings to be used as column headers.
|
236
237
|
# Valid options include :only and :except.
|
237
238
|
# See <tt>to_export</tt> for more details on the options.
|
238
|
-
#
|
239
|
+
#
|
239
240
|
# User.map_export_data(User.visible, :only => [:first_name, :last_name, :username])
|
240
241
|
# # => [['first_name', 'last_name', 'username'], ['John', 'Doe', 'johndoe'], ...]
|
241
242
|
#
|
@@ -269,7 +270,7 @@ module MakeExportable #:nodoc:
|
|
269
270
|
end
|
270
271
|
end
|
271
272
|
|
272
|
-
# <tt>validate_export_data_lengths</tt> ensures that the headers and all data rows are of the
|
273
|
+
# <tt>validate_export_data_lengths</tt> ensures that the headers and all data rows are of the
|
273
274
|
# same size. (This is an important data integrity check if you are using NoSQL.)
|
274
275
|
def validate_export_data_lengths(data_set, data_headers=nil)
|
275
276
|
row_length = !data_headers.blank? ? data_headers.size : data_set[0].size
|
@@ -283,13 +284,13 @@ module MakeExportable #:nodoc:
|
|
283
284
|
module InstanceMethods
|
284
285
|
|
285
286
|
# <tt>export_attribute</tt> returns the export value of an attribute or method.
|
286
|
-
# By default, this is simply the value of the attribute or method itself,
|
287
|
-
# but the value can be permanently overridden with another value by defining
|
288
|
-
# a method called "#{attribute}_export". The alternate method will *always*
|
289
|
-
# be called in place of the original one. At a minimum, this is useful
|
290
|
-
# when a date should be formatted when exporting or when booleans should
|
291
|
-
# always export as "Yes"/"No". But it can do more, performing any amount of
|
292
|
-
# processing or additional queries, as long as in the end it returns a value
|
287
|
+
# By default, this is simply the value of the attribute or method itself,
|
288
|
+
# but the value can be permanently overridden with another value by defining
|
289
|
+
# a method called "#{attribute}_export". The alternate method will *always*
|
290
|
+
# be called in place of the original one. At a minimum, this is useful
|
291
|
+
# when a date should be formatted when exporting or when booleans should
|
292
|
+
# always export as "Yes"/"No". But it can do more, performing any amount of
|
293
|
+
# processing or additional queries, as long as in the end it returns a value
|
293
294
|
# for the export to use.
|
294
295
|
# Sending an attribute name that does not exist will return an empty string.
|
295
296
|
def export_attribute(attribute)
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: make_exportable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 1.0.
|
9
|
+
- 2
|
10
|
+
version: 1.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Kevin Skoglund
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2010-06
|
19
|
+
date: 2010-08-06 00:00:00 -04:00
|
20
20
|
default_executable:
|
21
21
|
dependencies: []
|
22
22
|
|
@@ -30,6 +30,7 @@ extra_rdoc_files:
|
|
30
30
|
- README.rdoc
|
31
31
|
files:
|
32
32
|
- Gemfile
|
33
|
+
- Gemfile.lock
|
33
34
|
- MIT-LICENSE
|
34
35
|
- README.rdoc
|
35
36
|
- Rakefile
|