make_exportable 1.0.1 → 1.0.2
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/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
|