acts_as_reportable 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,63 @@
1
+ require "rake/rdoctask"
2
+ require "rake/testtask"
3
+ require "rake/gempackagetask"
4
+
5
+ AAR_VERSION = "1.0.0"
6
+
7
+ begin
8
+ require "rubygems"
9
+ rescue LoadError
10
+ nil
11
+ end
12
+
13
+ task :default => [:test]
14
+
15
+ Rake::TestTask.new do |test|
16
+ test.libs << "test"
17
+ test.test_files = Dir[ "test/*_test.rb" ]
18
+ test.verbose = true
19
+ end
20
+
21
+ spec = Gem::Specification.new do |spec|
22
+ spec.name = "acts_as_reportable"
23
+ spec.version = AAR_VERSION
24
+ spec.platform = Gem::Platform::RUBY
25
+ spec.summary = "ActiveRecord support for Ruby Reports"
26
+ spec.files = Dir.glob("{lib,test}/**/**/*") +
27
+ ["Rakefile"]
28
+ spec.require_path = "lib"
29
+
30
+ spec.test_files = Dir[ "test/*_test.rb" ]
31
+ spec.has_rdoc = true
32
+ #spec.extra_rdoc_files = %w{README LICENSE AUTHORS}
33
+ spec.rdoc_options << '--title' << 'Ruport Documentation'
34
+ spec.add_dependency('ruport', '>= 1.3.0')
35
+ spec.author = "Michael Milner"
36
+ spec.email = "mikem836@gmail.com"
37
+ spec.rubyforge_project = "ruport"
38
+ spec.homepage = "http://rubyreports.org"
39
+ spec.description = <<END_DESC
40
+ acts_as_reportable provides ActiveRecord support for Ruby Reports
41
+ END_DESC
42
+ end
43
+
44
+ Rake::RDocTask.new do |rdoc|
45
+ rdoc.rdoc_files.include( "lib/" )
46
+ rdoc.main = "README"
47
+ rdoc.rdoc_dir = "doc/html"
48
+ rdoc.title = "acts_as_reportable Documentation"
49
+ end
50
+
51
+ Rake::GemPackageTask.new(spec) do |pkg|
52
+ pkg.need_zip = true
53
+ pkg.need_tar = true
54
+ end
55
+
56
+ begin
57
+ require 'rcov/rcovtask'
58
+ Rcov::RcovTask.new do |t|
59
+ t.test_files = Dir[ "test/*_test.rb" ]
60
+ end
61
+ rescue LoadError
62
+ nil
63
+ end
@@ -0,0 +1,383 @@
1
+ # Ruport : Extensible Reporting System
2
+ #
3
+ # acts_as_reportable.rb provides ActiveRecord integration for Ruport.
4
+ #
5
+ # Originally created by Dudley Flanders, 2006
6
+ # Revised and updated by Michael Milner, 2007
7
+ # Copyright (C) 2006-2007 Dudley Flanders / Michael Milner, All Rights Reserved.
8
+ #
9
+ # This is free software distributed under the same terms as Ruby 1.8
10
+ # See LICENSE and COPYING for details.
11
+ #
12
+ require "ruport"
13
+ Ruport.quiet { require "active_record" }
14
+
15
+ module Ruport
16
+
17
+ # === Overview
18
+ #
19
+ # This module is designed to allow an ActiveRecord model to be converted to
20
+ # Ruport's data structures. If ActiveRecord is available when Ruport is
21
+ # loaded, this module will be automatically mixed into ActiveRecord::Base.
22
+ #
23
+ # Add the acts_as_reportable call to the model class that you want to
24
+ # integrate with Ruport:
25
+ #
26
+ # class Book < ActiveRecord::Base
27
+ # acts_as_reportable
28
+ # belongs_to :author
29
+ # end
30
+ #
31
+ # Then you can use the <tt>report_table</tt> method to get data from the
32
+ # model using ActiveRecord.
33
+ #
34
+ # Book.report_table(:all, :include => :author)
35
+ #
36
+ module Reportable
37
+
38
+ def self.included(base) #:nodoc:
39
+ base.extend ClassMethods
40
+ end
41
+
42
+ # === Overview
43
+ #
44
+ # This module contains class methods that will automatically be available
45
+ # to ActiveRecord models.
46
+ #
47
+ module ClassMethods
48
+
49
+ # In the ActiveRecord model you wish to integrate with Ruport, add the
50
+ # following line just below the class definition:
51
+ #
52
+ # acts_as_reportable
53
+ #
54
+ # Available options:
55
+ #
56
+ # <b><tt>:only</tt></b>:: an attribute name or array of attribute
57
+ # names to include in the results, other
58
+ # attributes will be excuded.
59
+ # <b><tt>:except</tt></b>:: an attribute name or array of attribute
60
+ # names to exclude from the results.
61
+ # <b><tt>:methods</tt></b>:: a method name or array of method names
62
+ # whose result(s) will be included in the
63
+ # table.
64
+ # <b><tt>:include</tt></b>:: an associated model or array of associated
65
+ # models to include in the results.
66
+ #
67
+ # Example:
68
+ #
69
+ # class Book < ActiveRecord::Base
70
+ # acts_as_reportable, :only => 'title', :include => :author
71
+ # end
72
+ #
73
+ def acts_as_reportable(options = {})
74
+ cattr_accessor :aar_options, :aar_columns
75
+
76
+ self.aar_options = options
77
+
78
+ include Ruport::Reportable::InstanceMethods
79
+ extend Ruport::Reportable::SingletonMethods
80
+ end
81
+ end
82
+
83
+ # === Overview
84
+ #
85
+ # This module contains methods that will be made available as singleton
86
+ # class methods to any ActiveRecord model that calls
87
+ # <tt>acts_as_reportable</tt>.
88
+ #
89
+ module SingletonMethods
90
+
91
+ # Creates a Ruport::Data::Table from an ActiveRecord find. Takes
92
+ # parameters just like a regular find.
93
+ #
94
+ # Additional options include:
95
+ #
96
+ # <b><tt>:only</tt></b>:: An attribute name or array of attribute
97
+ # names to include in the results, other
98
+ # attributes will be excuded.
99
+ # <b><tt>:except</tt></b>:: An attribute name or array of attribute
100
+ # names to exclude from the results.
101
+ # <b><tt>:methods</tt></b>:: A method name or array of method names
102
+ # whose result(s) will be included in the
103
+ # table.
104
+ # <b><tt>:include</tt></b>:: An associated model or array of associated
105
+ # models to include in the results.
106
+ # <b><tt>:filters</tt></b>:: A proc or array of procs that set up
107
+ # conditions to filter the data being added
108
+ # to the table.
109
+ # <b><tt>:transforms</tt></b>:: A proc or array of procs that perform
110
+ # transformations on the data being added
111
+ # to the table.
112
+ # <b><tt>:record_class</tt></b>:: Specify the class of the table's
113
+ # records.
114
+ # <b><tt>:eager_loading</tt></b>:: Set to false if you don't want to
115
+ # eager load included associations.
116
+ #
117
+ # The :only, :except, :methods, and :include options may also be passed
118
+ # to the :include option in order to specify the output for any
119
+ # associated models. In this case, the :include option must be a hash,
120
+ # where the keys are the names of the associations and the values
121
+ # are hashes of options.
122
+ #
123
+ # Any options passed to report_table will disable the options set by
124
+ # the acts_as_reportable class method.
125
+ #
126
+ # Example:
127
+ #
128
+ # class Book < ActiveRecord::Base
129
+ # belongs_to :author
130
+ # acts_as_reportable
131
+ # end
132
+ #
133
+ # Book.report_table(:all, :only => ['title'],
134
+ # :include => { :author => { :only => 'name' } }).as(:html)
135
+ #
136
+ # Returns:
137
+ #
138
+ # an html version of the table with two columns, title from
139
+ # the book, and name from the associated author.
140
+ #
141
+ # Example:
142
+ #
143
+ # Book.report_table(:all, :include => :author).as(:html)
144
+ #
145
+ # Returns:
146
+ #
147
+ # an html version of the table with all columns from books and authors.
148
+ #
149
+ # Note: column names for attributes of included models will be qualified
150
+ # with the name of the association.
151
+ #
152
+ def report_table(number = :all, options = {})
153
+ only = options.delete(:only)
154
+ except = options.delete(:except)
155
+ methods = options.delete(:methods)
156
+ includes = options.delete(:include)
157
+ filters = options.delete(:filters)
158
+ transforms = options.delete(:transforms)
159
+ record_class = options.delete(:record_class) || Ruport::Data::Record
160
+ self.aar_columns = []
161
+
162
+ unless options.delete(:eager_loading) == false
163
+ options[:include] = get_include_for_find(includes)
164
+ end
165
+
166
+ data = [find(number, options)].flatten
167
+ data = data.map {|r| r.reportable_data(:include => includes,
168
+ :only => only,
169
+ :except => except,
170
+ :methods => methods) }.flatten
171
+
172
+
173
+ table = Ruport::Data::Table.new(:data => data,
174
+ :column_names => aar_columns,
175
+ :record_class => record_class,
176
+ :filters => filters,
177
+ :transforms => transforms )
178
+ end
179
+
180
+ # Creates a Ruport::Data::Table from an ActiveRecord find_by_sql.
181
+ #
182
+ # Additional options include:
183
+ #
184
+ # <b><tt>:filters</tt></b>:: A proc or array of procs that set up
185
+ # conditions to filter the data being added
186
+ # to the table.
187
+ # <b><tt>:transforms</tt></b>:: A proc or array of procs that perform
188
+ # transformations on the data being added
189
+ # to the table.
190
+ # <b><tt>:record_class</tt></b>:: Specify the class of the table's
191
+ # records.
192
+ #
193
+ # Example:
194
+ #
195
+ # class Book < ActiveRecord::Base
196
+ # belongs_to :author
197
+ # acts_as_reportable
198
+ # end
199
+ #
200
+ # Book.report_table_by_sql("SELECT * FROM books")
201
+ #
202
+ def report_table_by_sql(sql, options = {})
203
+ record_class = options.delete(:record_class) || Ruport::Data::Record
204
+ filters = options.delete(:filters)
205
+ transforms = options.delete(:transforms)
206
+ self.aar_columns = []
207
+
208
+ data = find_by_sql(sql)
209
+ data = data.map {|r| r.reportable_data }.flatten
210
+
211
+ table = Ruport::Data::Table.new(:data => data,
212
+ :column_names => aar_columns,
213
+ :record_class => record_class,
214
+ :filters => filters,
215
+ :transforms => transforms)
216
+ end
217
+
218
+ private
219
+
220
+ def get_include_for_find(report_option)
221
+ includes = report_option.blank? ? aar_options[:include] : report_option
222
+ if includes.is_a?(Hash)
223
+ result = {}
224
+ includes.each do |k,v|
225
+ if v.empty? || !v[:include]
226
+ result.merge!(k => {})
227
+ else
228
+ result.merge!(k => get_include_for_find(v[:include]))
229
+ end
230
+ end
231
+ result
232
+ elsif includes.is_a?(Array)
233
+ result = {}
234
+ includes.each {|i| result.merge!(i => {}) }
235
+ result
236
+ else
237
+ includes
238
+ end
239
+ end
240
+ end
241
+
242
+ # === Overview
243
+ #
244
+ # This module contains methods that will be made available as instance
245
+ # methods to any ActiveRecord model that calls <tt>acts_as_reportable</tt>.
246
+ #
247
+ module InstanceMethods
248
+
249
+ # Grabs all of the object's attributes and the attributes of the
250
+ # associated objects and returns them as an array of record hashes.
251
+ #
252
+ # Associated object attributes are stored in the record with
253
+ # "association.attribute" keys.
254
+ #
255
+ # Passing :only as an option will only get those attributes.
256
+ # Passing :except as an option will exclude those attributes.
257
+ # Must pass :include as an option to access associations. Options
258
+ # may be passed to the included associations by providing the :include
259
+ # option as a hash.
260
+ # Passing :methods as an option will include any methods on the object.
261
+ #
262
+ # Example:
263
+ #
264
+ # class Book < ActiveRecord::Base
265
+ # belongs_to :author
266
+ # acts_as_reportable
267
+ # end
268
+ #
269
+ # abook.reportable_data(:only => ['title'], :include => [:author])
270
+ #
271
+ # Returns:
272
+ #
273
+ # [{'title' => 'book title',
274
+ # 'author.id' => 'author id',
275
+ # 'author.name' => 'author name' }]
276
+ #
277
+ # NOTE: title will only be returned if the value exists in the table.
278
+ # If the books table does not have a title column, it will not be
279
+ # returned.
280
+ #
281
+ # Example:
282
+ #
283
+ # abook.reportable_data(:only => ['title'],
284
+ # :include => { :author => { :only => ['name'] } })
285
+ #
286
+ # Returns:
287
+ #
288
+ # [{'title' => 'book title',
289
+ # 'author.name' => 'author name' }]
290
+ #
291
+ def reportable_data(options = {})
292
+ options = options.merge(self.class.aar_options) unless
293
+ has_report_options?(options)
294
+
295
+ data_records = [get_attributes_with_options(options)]
296
+ Array(options[:methods]).each do |method|
297
+ if options[:qualify_attribute_names]
298
+ m = "#{options[:qualify_attribute_names]}.#{method}"
299
+ else
300
+ m = "#{method}"
301
+ end
302
+ data_records.first[m] = send(method)
303
+ end
304
+
305
+ # Reorder columns to match options[:only]
306
+ self.class.aar_columns = options[:only] if Array === options[:only]
307
+
308
+ self.class.aar_columns |= data_records.first.keys
309
+
310
+ data_records =
311
+ add_includes(data_records, options[:include]) if options[:include]
312
+ data_records
313
+ end
314
+
315
+ private
316
+
317
+ # Add data for all included associations
318
+ #
319
+ def add_includes(data_records, includes)
320
+ include_has_options = includes.is_a?(Hash)
321
+ associations = include_has_options ? includes.keys : Array(includes)
322
+
323
+ associations.each do |association|
324
+ existing_records = data_records.dup
325
+ data_records = []
326
+
327
+ if include_has_options
328
+ assoc_options = includes[association].merge({
329
+ :qualify_attribute_names => association })
330
+ else
331
+ assoc_options = { :qualify_attribute_names => association }
332
+ end
333
+
334
+ association_objects = [send(association)].flatten.compact
335
+
336
+ existing_records.each do |existing_record|
337
+ if association_objects.empty?
338
+ data_records << existing_record
339
+ else
340
+ association_objects.each do |obj|
341
+ association_records = obj.reportable_data(assoc_options)
342
+ association_records.each do |assoc_record|
343
+ data_records << existing_record.merge(assoc_record)
344
+ end
345
+ self.class.aar_columns |= data_records.last.keys
346
+ end
347
+ end
348
+ end
349
+ end
350
+ data_records
351
+ end
352
+
353
+ # Check if the options hash has any report options
354
+ # (:only, :except, :methods, or :include).
355
+ #
356
+ def has_report_options?(options)
357
+ options[:only] || options[:except] || options[:methods] ||
358
+ options[:include]
359
+ end
360
+
361
+ # Get the object's attributes using the supplied options.
362
+ #
363
+ # Use the :only or :except options to limit the attributes returned.
364
+ #
365
+ # Use the :qualify_attribute_names option to append the association
366
+ # name to the attribute name as association.attribute
367
+ #
368
+ def get_attributes_with_options(options = {})
369
+ only_or_except =
370
+ if options[:only] or options[:except]
371
+ { :only => options[:only], :except => options[:except] }
372
+ end
373
+ attrs = attributes(only_or_except)
374
+ attrs = attrs.inject({}) {|h,(k,v)|
375
+ h["#{options[:qualify_attribute_names]}.#{k}"] = v; h
376
+ } if options[:qualify_attribute_names]
377
+ attrs
378
+ end
379
+ end
380
+ end
381
+ end
382
+
383
+ ActiveRecord::Base.send :include, Ruport::Reportable
@@ -0,0 +1,279 @@
1
+ class Array
2
+ def to_table(columns)
3
+ Table(columns) { |t| each { |r| t << r } }
4
+ end
5
+ end
6
+
7
+
8
+ #!/usr/bin/env ruby -w
9
+ require File.join(File.expand_path(File.dirname(__FILE__)), "helpers")
10
+
11
+ begin
12
+ require "mocha"
13
+ require "stubba"
14
+ Ruport.quiet { require "active_record" }
15
+ rescue LoadError
16
+ nil
17
+ end
18
+
19
+ if Object.const_defined?(:ActiveRecord) && Object.const_defined?(:Mocha)
20
+
21
+ require "ruport/acts_as_reportable"
22
+
23
+ class Team < ActiveRecord::Base
24
+ acts_as_reportable :except => 'id', :include => :players
25
+ has_many :players
26
+ end
27
+
28
+ class Player < ActiveRecord::Base
29
+ acts_as_reportable
30
+ belongs_to :team
31
+ belongs_to :personal_trainer
32
+
33
+ def stats
34
+ "#{name} stats"
35
+ end
36
+ end
37
+
38
+ module SomeModule
39
+ class PersonalTrainer < ActiveRecord::Base
40
+ acts_as_reportable
41
+ has_one :team
42
+ has_many :players
43
+ end
44
+ end
45
+
46
+ module ModelStubsSetup
47
+ Column = ActiveRecord::ConnectionAdapters::Column
48
+ PersonalTrainer = SomeModule::PersonalTrainer
49
+
50
+ def setup
51
+ setup_column_stubs
52
+
53
+ @trainers = []
54
+ @trainers << PersonalTrainer.new(:name => "Trainer 1")
55
+ @trainers << PersonalTrainer.new(:name => "Trainer 2")
56
+ @teams = []
57
+ @teams << Team.new( :name => "Testers",
58
+ :league => "My League")
59
+ @teams << Team.new( :name => "Others",
60
+ :league => "Other League")
61
+ @players = []
62
+ @players << Player.new( :team_id => 1,
63
+ :name => "Player 1",
64
+ :personal_trainer_id => 1)
65
+ @players << Player.new( :team_id => 1,
66
+ :name => "Player 2",
67
+ :personal_trainer_id => 2)
68
+
69
+ setup_find_stubs
70
+ end
71
+
72
+ private
73
+
74
+ def setup_column_stubs
75
+ PersonalTrainer.stubs(:columns).returns([
76
+ Column.new("id", nil, "integer", false),
77
+ Column.new("name", nil, "string", false)])
78
+ Team.stubs(:columns).returns([Column.new("id", nil, "integer", false),
79
+ Column.new("name", nil, "string", false),
80
+ Column.new("league", nil, "string", true)])
81
+ Player.stubs(:columns).returns([Column.new("id", nil, "integer", false),
82
+ Column.new("team_id", nil, "integer", true),
83
+ Column.new("name", nil, "string", false),
84
+ Column.new("personal_trainer_id", nil, "integer", true)])
85
+ end
86
+
87
+ def setup_find_stubs
88
+ PersonalTrainer.stubs(:find).returns(@trainers)
89
+ @trainers[0].stubs(:players).returns([@players[0]])
90
+ @trainers[1].stubs(:players).returns([@players[1]])
91
+ Team.stubs(:find).returns(@teams)
92
+ @teams[0].stubs(:players).returns(@players)
93
+ @teams[1].stubs(:players).returns([])
94
+ Player.stubs(:find).returns(@players)
95
+ Player.stubs(:find_by_sql).returns(@players)
96
+ @players[0].stubs(:team).returns(@teams[0])
97
+ @players[1].stubs(:team).returns(@teams[0])
98
+ @players[0].stubs(:personal_trainer).returns(@trainers[0])
99
+ @players[1].stubs(:personal_trainer).returns(@trainers[1])
100
+ end
101
+ end
102
+
103
+
104
+ class TestActsAsReportableClassMethods < Test::Unit::TestCase
105
+
106
+ def test_aar_options_set
107
+ assert_equal({:except => 'id', :include => :players}, Team.aar_options)
108
+ end
109
+ end
110
+
111
+ class TestActsAsReportableSingletonMethods < Test::Unit::TestCase
112
+ include ModelStubsSetup
113
+
114
+ def test_basic_report_table
115
+ actual = Player.report_table
116
+ expected = [[1, "Player 1", 1],
117
+ [1, "Player 2", 2]].to_table(%w[team_id name personal_trainer_id])
118
+ assert_equal expected, actual
119
+ end
120
+
121
+ def test_report_table_by_sql
122
+ actual = Player.report_table_by_sql("SELECT * FROM players")
123
+ expected = [[1, "Player 1", 1],
124
+ [1, "Player 2", 2]].to_table(%w[team_id name personal_trainer_id])
125
+ assert_equal expected, actual
126
+ end
127
+
128
+ def test_only_option
129
+ actual = Player.report_table(:all, :only => 'name')
130
+ expected = [["Player 1"],["Player 2"]].to_table(%w[name])
131
+ assert_equal expected, actual
132
+ end
133
+
134
+ def test_only_option_preserves_column_sort_order
135
+ column_order = %w[name personal_trainer_id team_id]
136
+ actual = Player.report_table(:all, :only => column_order)
137
+ expected = [["Player 1", 1, 1],
138
+ ["Player 2", 2, 1]].to_table(column_order)
139
+ assert_equal expected, actual
140
+ end
141
+
142
+ def test_except_option
143
+ actual = Player.report_table(:all, :except => 'personal_trainer_id')
144
+ expected = [[1, "Player 1"],[1, "Player 2"]].to_table(%w[team_id name])
145
+ assert_equal expected, actual
146
+ end
147
+
148
+ def test_methods_option
149
+ actual = Player.report_table(:all, :only => 'name', :methods => :stats)
150
+ expected = [["Player 1", "Player 1 stats"],
151
+ ["Player 2", "Player 2 stats"]].to_table(%w[name stats])
152
+ assert_equal expected, actual
153
+ end
154
+
155
+ def test_include_option
156
+ actual = Player.report_table(:all, :only => 'name',
157
+ :include => :personal_trainer)
158
+ expected = [["Player 1", "Trainer 1"],
159
+ ["Player 2", "Trainer 2"]].to_table(%w[name personal_trainer.name])
160
+ assert_equal expected, actual
161
+ end
162
+
163
+ def test_column_sorting_works_with_include_option
164
+ actual = Player.report_table(:all,
165
+ :only => %w[name personal_trainer.name],
166
+ :include => { :personal_trainer => { :only => %w[name] } })
167
+ expected = [["Player 1", "Trainer 1"],
168
+ ["Player 2", "Trainer 2"]].to_table(%w[name personal_trainer.name])
169
+ assert_equal expected, actual
170
+
171
+ actual = Player.report_table(:all,
172
+ :only => %w[personal_trainer.name name],
173
+ :include => { :personal_trainer => { :only => %w[name] } })
174
+ expected = [["Trainer 1", "Player 1"],
175
+ ["Trainer 2", "Player 2"]].to_table(%w[personal_trainer.name name])
176
+ assert_equal expected, actual
177
+ end
178
+
179
+ def test_include_has_options
180
+ actual = Team.report_table(:all, :only => 'name',
181
+ :include => { :players => { :only => 'name' } })
182
+ expected = [["Testers", "Player 1"],
183
+ ["Testers", "Player 2"],
184
+ ["Others", nil]].to_table(%w[name players.name])
185
+ assert_equal expected, actual
186
+ end
187
+
188
+ class CustomRecord < Ruport::Data::Record; end
189
+
190
+ def test_record_class_option
191
+ actual = Player.report_table(:all, :record_class => CustomRecord)
192
+ actual.each { |r| assert_equal CustomRecord, r.class }
193
+
194
+ actual = Player.report_table_by_sql("SELECT * FROM players",
195
+ :record_class => CustomRecord)
196
+ actual.each { |r| assert_equal CustomRecord, r.class }
197
+ end
198
+
199
+ def test_get_include_for_find
200
+ assert_equal :players, Team.send(:get_include_for_find, nil)
201
+ assert_equal nil, Player.send(:get_include_for_find, nil)
202
+ assert_equal :team, Player.send(:get_include_for_find, :team)
203
+ expected = {:team => {}}
204
+ assert_equal expected,
205
+ Player.send(:get_include_for_find, {:team => {:except => 'id'}})
206
+ expected = {:team => {:a => {}, :b => {}},
207
+ :c => {:d => {:e => {}, :f => {}}},
208
+ :g => {}}
209
+ assert_equal expected,
210
+ Player.send(:get_include_for_find, {:team => {:include => [:a,:b]},
211
+ :c => {:include => {:d => {:include => [:e,:f]}}}, :g => {}})
212
+ end
213
+ end
214
+
215
+ class TestActsAsReportableInstanceMethods < Test::Unit::TestCase
216
+ include ModelStubsSetup
217
+
218
+ def test_reportable_data
219
+ actual = @players[0].reportable_data
220
+ expected = [{ 'team_id' => 1,
221
+ 'name' => "Player 1",
222
+ 'personal_trainer_id' => 1 }]
223
+ assert_equal expected, actual
224
+
225
+ actual = @teams[0].reportable_data(:include =>
226
+ { :players => { :only => 'name' } })
227
+ expected = [{ 'name' => "Testers",
228
+ 'league' => "My League",
229
+ 'players.name' => "Player 1" },
230
+ { 'name' => "Testers",
231
+ 'league' => "My League",
232
+ 'players.name' => "Player 2" }]
233
+ assert_equal expected, actual
234
+ end
235
+
236
+ def test_add_includes
237
+ actual = @players[0].send(:add_includes,
238
+ [{ 'name' => "Player 1" }], :personal_trainer)
239
+ expected = [{ 'name' => "Player 1",
240
+ 'personal_trainer.name' => "Trainer 1" }]
241
+ assert_equal expected, actual
242
+ end
243
+
244
+ def test_has_report_options
245
+ assert @teams[0].send(:has_report_options?, { :only => 'name' })
246
+ assert @teams[0].send(:has_report_options?, { :except => 'name' })
247
+ assert @teams[0].send(:has_report_options?, { :methods => 'name' })
248
+ assert @teams[0].send(:has_report_options?, { :include => 'name' })
249
+ assert !@teams[0].send(:has_report_options?, { :foo => 'name' })
250
+ end
251
+
252
+ def test_get_attributes_with_options
253
+ actual = @players[0].send(:get_attributes_with_options)
254
+ expected = { 'team_id' => 1,
255
+ 'name' => "Player 1",
256
+ 'personal_trainer_id' => 1 }
257
+ assert_equal expected, actual
258
+
259
+ actual = @players[0].send(:get_attributes_with_options,
260
+ { :only => 'name' })
261
+ expected = { 'name' => "Player 1" }
262
+ assert_equal expected, actual
263
+
264
+ actual = @players[0].send(:get_attributes_with_options,
265
+ { :except => 'personal_trainer_id' })
266
+ expected = { 'team_id' => 1,
267
+ 'name' => "Player 1" }
268
+ assert_equal expected, actual
269
+
270
+ actual = @players[0].send(:get_attributes_with_options,
271
+ { :only => 'name', :qualify_attribute_names => :players })
272
+ expected = { 'players.name' => "Player 1" }
273
+ assert_equal expected, actual
274
+ end
275
+ end
276
+
277
+ else
278
+ $stderr.puts "Warning: Mocha and/or ActiveRecord not found -- skipping AAR tests"
279
+ end
data/test/helpers.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "test/unit"
2
+ begin; require "rubygems"; rescue LoadError; nil; end
3
+ require "ruport"
4
+ require "spec-unit"
5
+
6
+ class Test::Unit::TestCase
7
+ include SpecUnit
8
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.2
3
+ specification_version: 1
4
+ name: acts_as_reportable
5
+ version: !ruby/object:Gem::Version
6
+ version: 1.0.0
7
+ date: 2007-12-25 00:00:00 -05:00
8
+ summary: ActiveRecord support for Ruby Reports
9
+ require_paths:
10
+ - lib
11
+ email: mikem836@gmail.com
12
+ homepage: http://rubyreports.org
13
+ rubyforge_project: ruport
14
+ description: acts_as_reportable provides ActiveRecord support for Ruby Reports
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Michael Milner
31
+ files:
32
+ - lib/ruport
33
+ - lib/ruport/acts_as_reportable.rb
34
+ - test/helpers.rb
35
+ - test/acts_as_reportable_test.rb
36
+ - Rakefile
37
+ test_files:
38
+ - test/acts_as_reportable_test.rb
39
+ rdoc_options:
40
+ - --title
41
+ - Ruport Documentation
42
+ extra_rdoc_files: []
43
+
44
+ executables: []
45
+
46
+ extensions: []
47
+
48
+ requirements: []
49
+
50
+ dependencies:
51
+ - !ruby/object:Gem::Dependency
52
+ name: ruport
53
+ version_requirement:
54
+ version_requirements: !ruby/object:Gem::Version::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: 1.3.0
59
+ version: