rexport 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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +17 -0
  4. data/Rakefile +38 -0
  5. data/app/helpers/exports_helper.rb +25 -0
  6. data/app/views/export_filters/_export_filter.html.erb +7 -0
  7. data/app/views/export_items/_export_item.html.erb +8 -0
  8. data/app/views/export_items/edit.html.erb +15 -0
  9. data/app/views/exports/_edit.html.erb +7 -0
  10. data/app/views/exports/_filters.html.erb +9 -0
  11. data/app/views/exports/_form.html.erb +25 -0
  12. data/app/views/exports/_local_form.html.erb +1 -0
  13. data/app/views/exports/_rexport_model.html.erb +17 -0
  14. data/app/views/exports/_show.html.erb +53 -0
  15. data/app/views/exports/edit.html.erb +1 -0
  16. data/app/views/exports/index.html.erb +33 -0
  17. data/app/views/exports/new.html.erb +7 -0
  18. data/app/views/exports/show.html.erb +1 -0
  19. data/config/routes.rb +11 -0
  20. data/db/migrate/20091105182959_create_export_tables.rb +34 -0
  21. data/lib/rexport.rb +17 -0
  22. data/lib/rexport/data_fields.rb +152 -0
  23. data/lib/rexport/export_filter_methods.rb +34 -0
  24. data/lib/rexport/export_filters_controller_methods.rb +13 -0
  25. data/lib/rexport/export_item_methods.rb +45 -0
  26. data/lib/rexport/export_item_sortings_controller_methods.rb +13 -0
  27. data/lib/rexport/export_items_controller_methods.rb +32 -0
  28. data/lib/rexport/export_methods.rb +272 -0
  29. data/lib/rexport/exports_controller_methods.rb +86 -0
  30. data/lib/rexport/tree_node.rb +45 -0
  31. data/lib/rexport/version.rb +3 -0
  32. data/test/factories.rb +86 -0
  33. data/test/jenkins.bash +3 -0
  34. data/test/log/test.log +61761 -0
  35. data/test/test_helper.rb +168 -0
  36. data/test/unit/data_field_test.rb +25 -0
  37. data/test/unit/data_fields_test.rb +117 -0
  38. data/test/unit/export_methods_test.rb +97 -0
  39. data/test/unit/rexport_model_test.rb +35 -0
  40. data/test/unit/tree_node_test.rb +43 -0
  41. metadata +165 -0
@@ -0,0 +1,168 @@
1
+ require 'minitest/autorun'
2
+ require 'rubygems'
3
+ require 'active_record'
4
+ require 'active_support/test_case'
5
+ require 'logger'
6
+ require 'factory_girl'
7
+ require File.dirname(__FILE__) + '/factories'
8
+ require File.dirname(__FILE__) + '/../lib/rexport/data_fields'
9
+ require File.dirname(__FILE__) + '/../lib/rexport/export_methods'
10
+ require File.dirname(__FILE__) + '/../lib/rexport/export_item_methods'
11
+ require File.dirname(__FILE__) + '/../lib/rexport/export_filter_methods'
12
+ require File.dirname(__FILE__) + '/../lib/rexport/tree_node'
13
+
14
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
15
+
16
+ RAILS_DEFAULT_LOGGER = Logger.new(File.dirname(__FILE__) + '/log/test.log')
17
+ RAILS_DEFAULT_LOGGER.level = Logger::DEBUG
18
+ ActiveRecord::Base.logger = RAILS_DEFAULT_LOGGER
19
+
20
+ class ActiveSupport::TestCase
21
+ include Rexport::Factories
22
+
23
+ def setup
24
+ setup_db
25
+ Enrollment.instance_variable_set('@rexport_fields', nil)
26
+ Student.instance_variable_set('@rexport_fields', nil)
27
+ end
28
+
29
+ def teardown
30
+ teardown_db
31
+ end
32
+
33
+ # Placeholder so test/unit ignores test cases without any tests.
34
+ def default_test
35
+ end
36
+
37
+ private
38
+
39
+ def setup_db
40
+ old_stdout = $stdout
41
+ $stdout = StringIO.new
42
+
43
+ ActiveRecord::Schema.define(:version => 1) do
44
+ create_table :enrollments do |t|
45
+ t.integer :student_id, :status_id, :grade
46
+ t.boolean :active
47
+ t.timestamps
48
+ end
49
+
50
+ create_table :students do |t|
51
+ t.integer :family_id
52
+ t.string :name
53
+ t.date :date_of_birth
54
+ t.timestamps
55
+ end
56
+
57
+ create_table :families do |t|
58
+ t.string :name
59
+ t.timestamps
60
+ end
61
+
62
+ create_table :statuses do |t|
63
+ t.string :name
64
+ end
65
+
66
+ create_table :exports do |t|
67
+ t.string :name
68
+ t.string :model_name
69
+ t.text :description
70
+ end
71
+
72
+ create_table :export_items do |t|
73
+ t.integer :export_id
74
+ t.string :name, :rexport_field
75
+ t.integer :position
76
+ end
77
+
78
+ create_table :export_filters do |t|
79
+ t.integer :export_id
80
+ t.string :filter_field, :value
81
+ end
82
+
83
+ create_table :self_referential_checks do |t|
84
+ end
85
+ end
86
+
87
+ $stdout = old_stdout
88
+ end
89
+
90
+ def teardown_db
91
+ ActiveRecord::Base.connection.tables.each do |table|
92
+ ActiveRecord::Base.connection.drop_table(table)
93
+ end
94
+ end
95
+ end
96
+
97
+ class ActiveRecord::Base
98
+ class << self
99
+ def acts_as_list(options = {})
100
+ end
101
+ end
102
+ end
103
+
104
+ class Enrollment < ActiveRecord::Base
105
+ include Rexport::DataFields
106
+ belongs_to :student
107
+ belongs_to :status
108
+ belongs_to :ilp_status, :class_name => 'Status', :foreign_key => 'ilp_status_id'
109
+ belongs_to :self_referential_check
110
+
111
+ def foo
112
+ 'bar'
113
+ end
114
+
115
+ private
116
+
117
+ def Enrollment.initialize_local_rexport_fields
118
+ add_rexport_field(:foo_method, :method => :foo)
119
+ add_rexport_field(:bad_method, :method => 'bad_method')
120
+ add_association_methods(:associations => %w(status ilp_status))
121
+ end
122
+ end
123
+
124
+ class Student < ActiveRecord::Base
125
+ include Rexport::DataFields
126
+ belongs_to :family
127
+ has_many :enrollments
128
+ end
129
+
130
+ class Family < ActiveRecord::Base
131
+ include Rexport::DataFields
132
+ has_many :students
133
+
134
+ def foo
135
+ 'bar'
136
+ end
137
+
138
+ private
139
+
140
+ def Family.initialize_local_rexport_fields
141
+ add_rexport_field(:foo_method, :method => :foo)
142
+ end
143
+ end
144
+
145
+ class Status < ActiveRecord::Base
146
+ # does not include Rexport
147
+ has_many :enrollments
148
+ end
149
+
150
+ class Export < ActiveRecord::Base
151
+ include Rexport::ExportMethods
152
+ end
153
+
154
+ class ExportItem < ActiveRecord::Base
155
+ include Rexport::ExportItemMethods
156
+ end
157
+
158
+ class ExportFilter < ActiveRecord::Base
159
+ include Rexport::ExportFilterMethods
160
+ end
161
+
162
+ class SelfReferentialCheck < ActiveRecord::Base
163
+ belongs_to :enrollment
164
+
165
+ def SelfReferentialCheck.rexport_fields
166
+ 'trick get_rexport_models into believing we are exportable'
167
+ end
168
+ end
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+
3
+ class DataFieldTest < ActiveSupport::TestCase
4
+ def test_should_stringify_name
5
+ assert_equal('foo', Rexport::DataField.new(:foo).name)
6
+ end
7
+
8
+ def test_should_use_name_for_method
9
+ assert_equal('foo', Rexport::DataField.new(:foo).method)
10
+ end
11
+
12
+ def test_should_save_method
13
+ assert_equal('bar', Rexport::DataField.new(:foo, :method => :bar).method)
14
+ end
15
+
16
+ def test_should_save_type
17
+ assert_equal(:type_test, Rexport::DataField.new(:test, :type => :type_test).type)
18
+ end
19
+
20
+ def test_should_sort_data_fields
21
+ a = Rexport::DataField.new(:a)
22
+ b = Rexport::DataField.new(:b)
23
+ assert_equal([a,b], [b,a].sort)
24
+ end
25
+ end
@@ -0,0 +1,117 @@
1
+ require 'test_helper'
2
+
3
+ class DataFieldsTest < ActiveSupport::TestCase
4
+
5
+ class RexportClassMethodsTest < DataFieldsTest
6
+ def test_should_initialize_local_rexport_fields
7
+ assert_kind_of(Hash, Enrollment.rexport_fields)
8
+ assert_equal(%w(active bad_method created_at foo_method grade ilp_status_name status_name updated_at), Enrollment.rexport_fields.keys.sort)
9
+ assert_equal('grade', Enrollment.rexport_fields[:grade].method)
10
+ assert_equal('foo', Enrollment.rexport_fields[:foo_method].method)
11
+ assert_equal(:boolean, Enrollment.rexport_fields[:active].type)
12
+ assert_equal(:integer, Enrollment.rexport_fields[:grade].type)
13
+ end
14
+
15
+ def test_should_return_sorted_data_fields_array
16
+ assert_equal(%w(active bad_method created_at foo_method grade ilp_status_name status_name updated_at),
17
+ Enrollment.rexport_fields_array.map {|df| df.name})
18
+ end
19
+
20
+ def test_should_add_single_association_method_to_rexport_fields
21
+ assert_difference('Enrollment.rexport_fields.length') do
22
+ Enrollment.add_association_methods(:associations => 'test_association')
23
+ end
24
+ assert_equal('test_association_name', Enrollment.rexport_fields[:test_association_name].name)
25
+ assert_equal('test_association.name', Enrollment.rexport_fields[:test_association_name].method)
26
+ end
27
+
28
+ def test_should_add_name_methods_for_multiple_associations
29
+ assert_difference('Enrollment.rexport_fields.length', 3) do
30
+ Enrollment.add_association_methods(:associations => %w(a b c))
31
+ end
32
+ end
33
+
34
+ def test_should_add_multiple_methods_for_multiple_associations
35
+ assert_difference('Enrollment.rexport_fields.length', 9) do
36
+ Enrollment.add_association_methods(:associations => %w(a1 a2 a3), :methods => %w(m1 m2 m3))
37
+ end
38
+ end
39
+
40
+ def test_should_get_rexport_methods
41
+ assert_equal(%w(grade), Enrollment.get_rexport_methods(:grade))
42
+ assert_equal(%w(status.name), Enrollment.get_rexport_methods(:status_name))
43
+ assert_equal(%w(undefined_rexport_field), Enrollment.get_rexport_methods('bad_association.test'))
44
+ assert_equal(%w(undefined_rexport_field), Enrollment.get_rexport_methods('student.bad_method'))
45
+ assert_equal(%w(student.name), Enrollment.get_rexport_methods('student.name'))
46
+ assert_equal(%w(student.family.foo), Enrollment.get_rexport_methods('student.family.foo_method'))
47
+ assert_equal(['student.family.foo', 'student.name', 'undefined_rexport_field', 'undefined_rexport_field', 'status.name', 'grade'],
48
+ Enrollment.get_rexport_methods('student.family.foo_method', 'student.name', 'student.bad_method', 'bad_association.test', 'status_name', 'grade'))
49
+ end
50
+
51
+ def test_should_remove_single_rexport_field
52
+ assert(Enrollment.rexport_fields[:grade])
53
+ assert(Enrollment.remove_rexport_fields(:grade))
54
+ assert_nil(Enrollment.rexport_fields[:grade])
55
+ end
56
+
57
+ def test_should_remove_multiple_rexport_fields
58
+ fields = %w(grade status_name foo_method)
59
+ fields.each {|field| assert(Enrollment.rexport_fields[field])}
60
+ assert(Enrollment.remove_rexport_fields(fields))
61
+ fields.each {|field| assert_nil(Enrollment.rexport_fields[field])}
62
+ end
63
+
64
+ def test_should_get_klass_from_assocations
65
+ assert_equal(Family, Enrollment.get_klass_from_associations('student', 'family'))
66
+ end
67
+
68
+ def test_should_rasie_no_method_error_for_missing_associations
69
+ assert_raise(NoMethodError) { Enrollment.get_klass_from_associations('not_an_association') }
70
+ end
71
+
72
+ def test_reset_column_information_with_rexport_reset
73
+ assert(Enrollment.rexport_fields)
74
+ assert(Enrollment.instance_variable_get('@rexport_fields'))
75
+ Enrollment.reset_column_information
76
+ assert_nil(Enrollment.instance_variable_get('@rexport_fields'))
77
+ end
78
+ end
79
+
80
+ class RexportInstanceMethodsTest < DataFieldsTest
81
+ def test_should_export_fields_for_record
82
+ enrollment = FactoryGirl.create(:enrollment)
83
+ assert_equal(%w(1), enrollment.export('grade'))
84
+ assert_equal(%w(bar), enrollment.export('foo'))
85
+ assert_equal([''], enrollment.export('bad_method'))
86
+ assert_equal(%w(1 bar) << Date.today.strftime("%m/%d/%y"), enrollment.export('grade', 'foo', 'updated_at'))
87
+ end
88
+
89
+ def test_should_handle_missing_associations
90
+ enrollment = Enrollment.new
91
+ assert_equal([''], enrollment.export('status.name'))
92
+ assert_equal([''], enrollment.export('student.name'))
93
+ end
94
+
95
+ def test_should_handle_undefined_export
96
+ enrollment = FactoryGirl.create(:enrollment)
97
+ assert_equal(['UNDEFINED EXPORT FIELD'], enrollment.export('undefined_rexport_field'))
98
+ end
99
+
100
+ def test_should_export_associated_fields
101
+ enrollment = FactoryGirl.create(:enrollment)
102
+ assert_equal(['Sammy Sample'], enrollment.export('student.name'))
103
+ assert_equal(['The Sample Family'], enrollment.export('student.family.name'))
104
+ assert_equal(%w(bar), enrollment.export('student.family.foo'))
105
+ end
106
+
107
+ def test_should_export_field_from_non_rexported_model
108
+ enrollment = FactoryGirl.create(:enrollment)
109
+ assert_equal(['active'], enrollment.export('status.name'))
110
+ end
111
+
112
+ def test_should_export_local_associated_and_non_rexported_fields
113
+ enrollment = FactoryGirl.create(:enrollment)
114
+ assert_equal(['The Sample Family', 'Sammy Sample', '1', 'bar', 'active'], enrollment.export('student.family.name', 'student.name', 'grade', 'student.family.foo', 'status.name'))
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,97 @@
1
+ require 'test_helper'
2
+
3
+ class ExportMethodsTest < ActiveSupport::TestCase
4
+ def test_should_return_header
5
+ export = FactoryGirl.create(:export)
6
+ assert_equal(['Family Name', 'Grade', 'Status', 'Bogus Item'], export.header)
7
+ end
8
+
9
+ def test_should_return_rexport_fields
10
+ export = FactoryGirl.create(:export)
11
+ assert_equal(%w(student.family.name grade status_name bogus_field), export.send(:rexport_fields))
12
+ end
13
+
14
+ def test_should_return_rexport_methods
15
+ export = FactoryGirl.create(:export)
16
+ assert_equal(%w(student.family.name grade status.name undefined_rexport_field), export.send(:rexport_methods))
17
+ end
18
+
19
+ def test_records
20
+ export = FactoryGirl.create(:export)
21
+ enrollment = FactoryGirl.create(:enrollment)
22
+ assert_equal(['The Sample Family', '1', 'active', 'UNDEFINED EXPORT FIELD'], export.records.first)
23
+ end
24
+
25
+ def test_records_with_filters
26
+ export = FactoryGirl.create(:export)
27
+ filtered_export = FactoryGirl.create(:export)
28
+ enrollment = FactoryGirl.create(:enrollment)
29
+ FactoryGirl.create(:second_grade_enrollment)
30
+ assert_equal(2, Enrollment.count)
31
+ assert_equal(2, export.records.length)
32
+ assert_equal(['The Sample Family', '1', 'active', 'UNDEFINED EXPORT FIELD'], filtered_export.records.first)
33
+ end
34
+
35
+ def test_sample_records
36
+ export = FactoryGirl.create(:export)
37
+ export.expects(:get_records).with(Rexport::SAMPLE_SIZE).returns(true)
38
+ assert(export.sample_records)
39
+ end
40
+
41
+ def test_to_s_with_no_records
42
+ export = FactoryGirl.create(:export)
43
+ assert_equal("Family Name|Grade|Status|Bogus Item\n", export.to_s)
44
+ end
45
+
46
+ def test_to_s_with_record
47
+ export = FactoryGirl.create(:export)
48
+ enrollment = FactoryGirl.create(:enrollment)
49
+ assert_equal("Family Name|Grade|Status|Bogus Item\nThe Sample Family|1|active|UNDEFINED EXPORT FIELD\n", export.to_s)
50
+ end
51
+
52
+ def test_to_csv_with_no_records
53
+ export = FactoryGirl.create(:export)
54
+ assert_equal("Family Name,Grade,Status,Bogus Item\n", export.to_csv)
55
+ end
56
+
57
+ def test_to_csv_with_record
58
+ export = FactoryGirl.create(:export)
59
+ enrollment = FactoryGirl.create(:enrollment)
60
+ assert_equal("Family Name,Grade,Status,Bogus Item\nThe Sample Family,1,active,UNDEFINED EXPORT FIELD\n", export.to_csv)
61
+ end
62
+
63
+ def test_to_csv_with_passed_objects
64
+ export = FactoryGirl.create(:export)
65
+ assert_equal("Family Name,Grade,Status,Bogus Item\n\"\",99,\"\",UNDEFINED EXPORT FIELD\n", export.to_csv([Enrollment.new(:grade => 99)]))
66
+ end
67
+
68
+ def test_build_conditions
69
+ export = FactoryGirl.create(:filtered_export)
70
+ assert_equal({'statuses.name' => 'active', 'enrollments.grade' => '1'}, export.send(:build_conditions))
71
+ end
72
+
73
+ def test_build_include
74
+ export = FactoryGirl.create(:export)
75
+ assert_equal([{:student=>[:family]}, :status], export.send(:build_include))
76
+ end
77
+
78
+ def test_should_return_rexport_models
79
+ export = FactoryGirl.create(:export)
80
+ assert_equal(%w(Enrollment Family SelfReferentialCheck Student), export.rexport_models.map {|m| m.klass.to_s}.sort)
81
+ assert_equal(['', 'self_referential_check', 'student', 'student.family'], export.rexport_models.map {|m| m.path.to_s}.sort)
82
+ end
83
+
84
+ def test_should_create_copy_with_unique_name
85
+ assert_equal 'Enrollment Export Copy', FactoryGirl.create(:export).copy.name
86
+ assert_equal 'Enrollment Export Copy [1]', FactoryGirl.create(:export).copy.name
87
+ assert_equal 'Enrollment Export Copy [2]', FactoryGirl.create(:export).copy.name
88
+ end
89
+
90
+ def test_should_copy_export_with_export_items
91
+ assert_equal FactoryGirl.create(:export).export_items.count, FactoryGirl.create(:export).copy.export_items.count
92
+ end
93
+
94
+ def test_should_copy_export_with_export_filters
95
+ assert_equal FactoryGirl.create(:filtered_export).export_filters.count, FactoryGirl.create(:filtered_export).copy.export_filters.count
96
+ end
97
+ end
@@ -0,0 +1,35 @@
1
+ require 'test_helper'
2
+
3
+ class RexportModel < ActiveSupport::TestCase
4
+ def test_return_correct_foreign_key
5
+ rexport_model = Rexport::RexportModel.new(Enrollment)
6
+
7
+ data_field = Enrollment.rexport_fields['status_name']
8
+ assert_equal('status_id', rexport_model.filter_column(data_field))
9
+
10
+ data_field = Enrollment.rexport_fields['ilp_status_name']
11
+ assert_equal('ilp_status_id', rexport_model.filter_column(data_field))
12
+ end
13
+
14
+ def test_should_call_rexport_fields_array
15
+ rexport_model = Rexport::RexportModel.new(Enrollment)
16
+ Enrollment.expects(:rexport_fields_array).returns(true)
17
+ assert(rexport_model.rexport_fields_array)
18
+ end
19
+
20
+ def test_field_path
21
+ rexport_model = Rexport::RexportModel.new(Enrollment, 'foo')
22
+ assert_equal('foo.bar', rexport_model.field_path('bar'))
23
+ end
24
+
25
+ def test_collection_from_association
26
+ rexport_model = Rexport::RexportModel.new(Enrollment)
27
+ Status.expects(:all).returns(true)
28
+ assert(rexport_model.collection_from_association('status'))
29
+ end
30
+
31
+ def test_should_return_class_name
32
+ rexport_model = Rexport::RexportModel.new(Enrollment)
33
+ assert_equal('Enrollment', rexport_model.name)
34
+ end
35
+ end
@@ -0,0 +1,43 @@
1
+ require 'test_helper'
2
+
3
+ class TreeNodeTest < ActiveSupport::TestCase
4
+ def test_should_initialize_with_name
5
+ t = Rexport::TreeNode.new('test')
6
+ assert_equal('test', t.name)
7
+ assert_equal([], t.children)
8
+ end
9
+
10
+ def test_should_initialize_with_name_and_children
11
+ t = Rexport::TreeNode.new('test', %w(one two three))
12
+ assert_equal('test', t.name)
13
+ assert_equal(["test", [["one", [["two", [["three", []]]]]]]], t.to_a)
14
+ end
15
+
16
+ def test_should_add_children
17
+ root = Rexport::TreeNode.new('root')
18
+ root.add_child('a')
19
+ assert_equal(['root', [['a', []]]], root.to_a)
20
+ root.add_child('a')
21
+ assert_equal(['root', [['a', []]]], root.to_a)
22
+ root.add_child('a', [1 , 2])
23
+ assert_equal(['root', [['a', [[1, [[2, []]]]]]]], root.to_a)
24
+ end
25
+
26
+ def test_should_return_empty_include
27
+ root = Rexport::TreeNode.new('root')
28
+ assert_equal([], root.to_include)
29
+ end
30
+
31
+ def test_should_return_single_level_array_include
32
+ root = Rexport::TreeNode.new('root')
33
+ %w(a b c).each {|l| root.add_child(l)}
34
+ assert_equal([:a, :b, :c], root.to_include)
35
+ end
36
+
37
+ def test_should_return_nested_hash_include
38
+ root = Rexport::TreeNode.new('root', %w(a b c))
39
+ assert_equal([{:a => [{:b => [:c]}]}], root.to_include)
40
+ root.add_child('b', 'one', 'two')
41
+ assert_equal([{:a => [{:b => [:c]}]}, {:b => [{:one =>[:two]}]}], root.to_include)
42
+ end
43
+ end