rexport 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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