mr 0.35.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.
Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/Gemfile +13 -0
  4. data/LICENSE +22 -0
  5. data/README.md +29 -0
  6. data/bench/all.rb +4 -0
  7. data/bench/factory.rb +68 -0
  8. data/bench/fake_record.rb +174 -0
  9. data/bench/model.rb +201 -0
  10. data/bench/read_model.rb +191 -0
  11. data/bench/results/factory.txt +21 -0
  12. data/bench/results/fake_record.txt +37 -0
  13. data/bench/results/model.txt +44 -0
  14. data/bench/results/read_model.txt +46 -0
  15. data/bench/setup.rb +132 -0
  16. data/lib/mr.rb +11 -0
  17. data/lib/mr/after_commit.rb +49 -0
  18. data/lib/mr/after_commit/fake_record.rb +39 -0
  19. data/lib/mr/after_commit/record.rb +48 -0
  20. data/lib/mr/after_commit/record_procs_methods.rb +82 -0
  21. data/lib/mr/factory.rb +82 -0
  22. data/lib/mr/factory/config.rb +240 -0
  23. data/lib/mr/factory/model_factory.rb +103 -0
  24. data/lib/mr/factory/model_stack.rb +28 -0
  25. data/lib/mr/factory/read_model_factory.rb +104 -0
  26. data/lib/mr/factory/record_factory.rb +130 -0
  27. data/lib/mr/factory/record_stack.rb +219 -0
  28. data/lib/mr/fake_query.rb +53 -0
  29. data/lib/mr/fake_record.rb +58 -0
  30. data/lib/mr/fake_record/associations.rb +257 -0
  31. data/lib/mr/fake_record/attributes.rb +168 -0
  32. data/lib/mr/fake_record/persistence.rb +116 -0
  33. data/lib/mr/json_field.rb +180 -0
  34. data/lib/mr/json_field/fake_record.rb +31 -0
  35. data/lib/mr/json_field/record.rb +38 -0
  36. data/lib/mr/model.rb +67 -0
  37. data/lib/mr/model/associations.rb +161 -0
  38. data/lib/mr/model/configuration.rb +67 -0
  39. data/lib/mr/model/fields.rb +177 -0
  40. data/lib/mr/model/persistence.rb +79 -0
  41. data/lib/mr/query.rb +126 -0
  42. data/lib/mr/read_model.rb +83 -0
  43. data/lib/mr/read_model/data.rb +38 -0
  44. data/lib/mr/read_model/fields.rb +218 -0
  45. data/lib/mr/read_model/query_expression.rb +188 -0
  46. data/lib/mr/read_model/querying.rb +214 -0
  47. data/lib/mr/read_model/set_querying.rb +82 -0
  48. data/lib/mr/read_model/subquery.rb +98 -0
  49. data/lib/mr/record.rb +35 -0
  50. data/lib/mr/test_helpers.rb +229 -0
  51. data/lib/mr/type_converter.rb +85 -0
  52. data/lib/mr/version.rb +3 -0
  53. data/log/.gitkeep +0 -0
  54. data/mr.gemspec +29 -0
  55. data/test/helper.rb +21 -0
  56. data/test/support/db.rb +10 -0
  57. data/test/support/factory.rb +13 -0
  58. data/test/support/factory/area.rb +6 -0
  59. data/test/support/factory/comment.rb +14 -0
  60. data/test/support/factory/image.rb +6 -0
  61. data/test/support/factory/user.rb +6 -0
  62. data/test/support/models/area.rb +58 -0
  63. data/test/support/models/comment.rb +60 -0
  64. data/test/support/models/image.rb +53 -0
  65. data/test/support/models/user.rb +96 -0
  66. data/test/support/read_model/querying.rb +150 -0
  67. data/test/support/read_models/comment_with_user_data.rb +27 -0
  68. data/test/support/read_models/set_data.rb +49 -0
  69. data/test/support/read_models/subquery_data.rb +41 -0
  70. data/test/support/read_models/user_with_area_data.rb +15 -0
  71. data/test/support/schema.rb +39 -0
  72. data/test/support/setup_test_db.rb +10 -0
  73. data/test/system/factory/model_factory_tests.rb +87 -0
  74. data/test/system/factory/model_stack_tests.rb +30 -0
  75. data/test/system/factory/record_factory_tests.rb +84 -0
  76. data/test/system/factory/record_stack_tests.rb +51 -0
  77. data/test/system/factory_tests.rb +32 -0
  78. data/test/system/read_model_tests.rb +199 -0
  79. data/test/system/with_model_tests.rb +275 -0
  80. data/test/unit/after_commit/fake_record_tests.rb +110 -0
  81. data/test/unit/after_commit/record_procs_methods_tests.rb +177 -0
  82. data/test/unit/after_commit/record_tests.rb +134 -0
  83. data/test/unit/after_commit_tests.rb +113 -0
  84. data/test/unit/factory/config_tests.rb +651 -0
  85. data/test/unit/factory/model_factory_tests.rb +473 -0
  86. data/test/unit/factory/model_stack_tests.rb +97 -0
  87. data/test/unit/factory/read_model_factory_tests.rb +195 -0
  88. data/test/unit/factory/record_factory_tests.rb +446 -0
  89. data/test/unit/factory/record_stack_tests.rb +549 -0
  90. data/test/unit/factory_tests.rb +213 -0
  91. data/test/unit/fake_query_tests.rb +137 -0
  92. data/test/unit/fake_record/associations_tests.rb +585 -0
  93. data/test/unit/fake_record/attributes_tests.rb +265 -0
  94. data/test/unit/fake_record/persistence_tests.rb +239 -0
  95. data/test/unit/fake_record_tests.rb +106 -0
  96. data/test/unit/json_field/fake_record_tests.rb +75 -0
  97. data/test/unit/json_field/record_tests.rb +80 -0
  98. data/test/unit/json_field_tests.rb +302 -0
  99. data/test/unit/model/associations_tests.rb +346 -0
  100. data/test/unit/model/configuration_tests.rb +92 -0
  101. data/test/unit/model/fields_tests.rb +278 -0
  102. data/test/unit/model/persistence_tests.rb +114 -0
  103. data/test/unit/model_tests.rb +137 -0
  104. data/test/unit/query_tests.rb +300 -0
  105. data/test/unit/read_model/data_tests.rb +56 -0
  106. data/test/unit/read_model/fields_tests.rb +416 -0
  107. data/test/unit/read_model/query_expression_tests.rb +381 -0
  108. data/test/unit/read_model/querying_tests.rb +613 -0
  109. data/test/unit/read_model/set_querying_tests.rb +149 -0
  110. data/test/unit/read_model/subquery_tests.rb +242 -0
  111. data/test/unit/read_model_tests.rb +187 -0
  112. data/test/unit/record_tests.rb +45 -0
  113. data/test/unit/test_helpers_tests.rb +431 -0
  114. data/test/unit/type_converter_tests.rb +207 -0
  115. metadata +285 -0
@@ -0,0 +1,84 @@
1
+ require 'assert'
2
+ require 'mr/factory/record_factory'
3
+
4
+ require 'test/support/setup_test_db'
5
+ require 'test/support/models/area'
6
+ require 'test/support/models/user'
7
+
8
+ class MR::Factory::RecordFactory
9
+
10
+ class SystemTests < DbTests
11
+ desc "MR::Factory::Model"
12
+ setup do
13
+ @factory_class = MR::Factory::RecordFactory
14
+ end
15
+
16
+ end
17
+
18
+ class BuildingRealRecordTests < SystemTests
19
+ setup do
20
+ @factory = @factory_class.new(UserRecord)
21
+ end
22
+ subject{ @factory }
23
+
24
+ should "build a record with its attributes set using `record`" do
25
+ user_record = subject.record
26
+ assert_instance_of UserRecord, user_record
27
+ assert_true user_record.new_record?
28
+ assert_kind_of String, user_record.name
29
+ assert_kind_of Integer, user_record.number
30
+ assert_kind_of Date, user_record.started_on
31
+ assert_kind_of Time, user_record.dob
32
+ assert_true user_record.salary.kind_of?(Float) || user_record.salary.kind_of?(BigDecimal)
33
+ assert_nil user_record.area_id
34
+ end
35
+
36
+ should "use the `sql_type` if there is no ActiveRecord `type`" do
37
+ # we have to undefine attribute methods to remove any casting that was
38
+ # cached by ActiveRecord, thus allowing us to write a String to the
39
+ # 'number' field which casts its inputs to Integer.
40
+ UserRecord.undefine_attribute_methods
41
+ number_column = UserRecord.columns.detect{ |c| c.name == "number" }
42
+ Assert.stub(number_column, :type){ nil }
43
+ Assert.stub(number_column, :sql_type){ 'string' }
44
+
45
+ user_record = @factory_class.new(UserRecord).record
46
+ assert_kind_of String, user_record.number
47
+ end
48
+
49
+ should "avoid setting a field if either `type` or `sql_type` is invalid" do
50
+ number_column = UserRecord.columns.detect{ |c| c.name == "number" }
51
+ Assert.stub(number_column, :type){ Factory.string }
52
+
53
+ user_record = @factory_class.new(UserRecord).record
54
+ assert_nil user_record.number
55
+
56
+ Assert.stub(number_column, :type){ nil }
57
+ Assert.stub(number_column, :sql_type){ Factory.string }
58
+
59
+ user_record = @factory_class.new(UserRecord).record
60
+ assert_nil user_record.number
61
+
62
+ Assert.stub(number_column, :type){ nil }
63
+ Assert.stub(number_column, :sql_type){ nil }
64
+
65
+ user_record = @factory_class.new(UserRecord).record
66
+ assert_nil user_record.number
67
+ end
68
+
69
+ should "build a record and save it using `saved_record`" do
70
+ area_factory = @factory_class.new(AreaRecord)
71
+ area_record = area_factory.record.tap(&:save)
72
+
73
+ user_record = subject.saved_record(:area => area_record)
74
+ assert_instance_of UserRecord, user_record
75
+ assert_false user_record.new_record?
76
+ end
77
+
78
+ should "build a record stack for an instance using `stack`" do
79
+ assert_instance_of MR::Factory::RecordStack, subject.stack
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -0,0 +1,51 @@
1
+ require 'assert'
2
+ require 'mr/factory/record_stack'
3
+
4
+ require 'test/support/setup_test_db'
5
+ require 'test/support/models/comment'
6
+
7
+ class MR::Factory::RecordStack
8
+
9
+ class SystemTests < DbTests
10
+ desc "MR::Factory::RecordStack"
11
+ setup do
12
+ @comment_record = CommentRecord.new(:parent_type => 'UserRecord')
13
+ @factory_config = MR::Factory::RecordFactory::Config.new(@comment_record.class)
14
+
15
+ @record_stack = MR::Factory::RecordStack.for_record(
16
+ @comment_record,
17
+ @factory_config
18
+ )
19
+ end
20
+ subject{ @record_stack }
21
+
22
+ should "build an instance of the model with all " \
23
+ "belongs to associations set" do
24
+ assert_instance_of CommentRecord, @comment_record
25
+ assert_true @comment_record.new_record?
26
+ assert_instance_of UserRecord, @comment_record.parent
27
+ assert_true @comment_record.parent.new_record?
28
+ assert_instance_of AreaRecord, @comment_record.parent.area
29
+ assert_true @comment_record.parent.area.new_record?
30
+ end
31
+
32
+ should "be able to create all the records and set foreign keys" do
33
+ assert_nothing_raised{ subject.create }
34
+ assert_false @comment_record.new_record?
35
+ assert_false @comment_record.parent.new_record?
36
+ assert_equal @comment_record.parent.id, @comment_record.parent_id
37
+ assert_false @comment_record.parent.area.new_record?
38
+ assert_equal @comment_record.parent.area_id, @comment_record.parent.area.id
39
+ end
40
+
41
+ should "be able to destroy all the records" do
42
+ subject.create
43
+ assert_nothing_raised{ subject.destroy }
44
+ assert_true @comment_record.destroyed?
45
+ assert_true @comment_record.parent.destroyed?
46
+ assert_true @comment_record.parent.area.destroyed?
47
+ end
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,32 @@
1
+ require 'assert'
2
+ require 'mr/factory'
3
+
4
+ require 'test/support/models/user'
5
+
6
+ module MR::Factory
7
+
8
+ class SystemTests < Assert::Context
9
+ desc "MR::Factory for records and models"
10
+ subject{ MR::Factory }
11
+
12
+ should "return a RecordFactory when a Record is passed to `new`" do
13
+ factory = subject.new(UserRecord)
14
+ assert_instance_of MR::Factory::RecordFactory, factory
15
+ end
16
+
17
+ should "return a ModelFactory when a Model is passed to `new`" do
18
+ factory = subject.new(User, UserRecord)
19
+ assert_instance_of MR::Factory::ModelFactory, factory
20
+ factory = subject.new(User, FakeUserRecord)
21
+ assert_instance_of MR::Factory::ModelFactory, factory
22
+ end
23
+
24
+ should "return a ReadModelFactory when a ReadModel is passed to `new`" do
25
+ read_model_class = Class.new{ include MR::ReadModel }
26
+ factory = subject.new(read_model_class)
27
+ assert_instance_of MR::Factory::ReadModelFactory, factory
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,199 @@
1
+ require 'assert'
2
+ require 'mr/read_model'
3
+
4
+ require 'mr/factory'
5
+ require 'test/support/setup_test_db'
6
+ require 'test/support/factory/area'
7
+ require 'test/support/factory/comment'
8
+ require 'test/support/factory/image'
9
+ require 'test/support/factory/user'
10
+ require 'test/support/read_models/comment_with_user_data'
11
+ require 'test/support/read_models/subquery_data'
12
+ require 'test/support/read_models/set_data'
13
+ require 'test/support/read_models/user_with_area_data'
14
+
15
+ module MR::ReadModel
16
+
17
+ class SystemTests < DbTests
18
+ desc "MR::ReadModel"
19
+
20
+ end
21
+
22
+ class FieldsSystemTests < SystemTests
23
+ desc "fields"
24
+ setup do
25
+ @area = Factory::Area.saved_instance
26
+ @user = Factory::User.saved_instance(:area => @area)
27
+ @image = Factory::Image.saved_instance(:user => @user)
28
+ @comment = Factory::Comment.saved_instance(:parent => @user)
29
+ @comment_with_user_data = CommentWithUserData.query.results.first
30
+ end
31
+ subject{ @comment_with_user_data }
32
+
33
+ should have_readers :comment_id, :comment_created_at
34
+ should have_readers :user_name, :user_number, :user_salary, :user_started_on
35
+ should have_readers :area_active, :area_meeting_time
36
+
37
+ should "know it's different model's data" do
38
+ # reload the comment/area -- force AR to type-cast it's columns, otherwise
39
+ # comment has whatever fake data it was given, which may not match up
40
+ # like Time != DateTime
41
+ @comment = Comment.find(@comment.id)
42
+ @image = Image.find(@image.id)
43
+ @user = User.find(@user.id)
44
+ @area = Area.find(@area.id)
45
+ assert_equal @comment.id, subject.comment_id
46
+ assert_equal @comment.created_at, subject.comment_created_at
47
+ assert_equal @user.name, subject.user_name
48
+ assert_equal @user.number, subject.user_number
49
+ assert_equal @user.salary, subject.user_salary
50
+ assert_equal @user.started_on, subject.user_started_on
51
+ assert_equal @user.dob, subject.user_dob
52
+ assert_equal @image.data, subject.image_data
53
+ assert_equal @area.active, subject.area_active
54
+ assert_equal @area.meeting_time, subject.area_meeting_time
55
+ assert_equal @area.description, subject.area_description
56
+ assert_equal @area.percentage, subject.area_percentage
57
+ end
58
+
59
+ end
60
+
61
+ class QuerySystemTests < SystemTests
62
+ desc "query"
63
+ setup do
64
+ @matching_user = Factory::User.instance_stack.tap(&:create).model
65
+ @not_matching_user = Factory::User.instance_stack.tap(&:create).model
66
+ @query = UserWithAreaData.query(@matching_user.area_id)
67
+ end
68
+ subject{ @query }
69
+
70
+ should "return an MR::Query" do
71
+ assert_instance_of MR::Query, subject
72
+ end
73
+
74
+ should "filter records based on the user's area" do
75
+ results = subject.results
76
+ assert_equal 1, results.size
77
+ assert_equal @matching_user.id, results.first.user_id
78
+ assert_equal @matching_user.area_id, results.first.area_id
79
+ end
80
+
81
+ end
82
+
83
+ class FindSystemTests < SystemTests
84
+ desc "find"
85
+ setup do
86
+ @matching_user = Factory::User.instance_stack.tap(&:create).model
87
+ @user_with_area_data = UserWithAreaData.find(@matching_user.id)
88
+ end
89
+ subject{ @user_with_area_data }
90
+
91
+ should "find a specific record by it's id" do
92
+ assert_kind_of UserWithAreaData, subject
93
+ assert_equal @matching_user.id, subject.user_id
94
+ end
95
+
96
+ end
97
+
98
+ class SubquerySetupTests < SystemTests
99
+ setup do
100
+ @user = Factory::User.saved_model({
101
+ :area => { :active => true }
102
+ })
103
+ @area = @user.area
104
+ @started_on = @user.started_on
105
+ @comment = Factory::Comment.saved_instance(:parent => @user)
106
+ end
107
+
108
+ end
109
+
110
+ class SubquerySystemTests < SubquerySetupTests
111
+ desc "query that uses subqueries"
112
+ setup do
113
+ @results = SubqueryData.query(:started_on => @started_on).results
114
+ end
115
+ subject{ @results }
116
+
117
+ should "have found the matching area, user and comment data" do
118
+ assert_equal 1, subject.size
119
+ assert_includes @area.id, subject.map(&:area_id)
120
+ assert_includes @user.id, subject.map(&:user_id)
121
+ assert_includes @comment.id, subject.map(&:comment_id)
122
+ end
123
+
124
+ end
125
+
126
+ class SubqueryFindSystemTests < SubquerySetupTests
127
+ desc "find that uses subqueries"
128
+ setup do
129
+ @result = SubqueryData.find(@area.id, :started_on => @started_on)
130
+ end
131
+ subject{ @result }
132
+
133
+ should "have found the matching area, user and comment data" do
134
+ assert_equal @area.id, subject.area_id
135
+ assert_equal @user.id, subject.user_id
136
+ assert_equal @comment.id, subject.comment_id
137
+ end
138
+
139
+ end
140
+
141
+ class SetOperatorSetupTests < SystemTests
142
+ setup do
143
+ @params = {
144
+ :match_start => Factory.string,
145
+ :other_match_start => Factory.string,
146
+ :match_end => Factory.string,
147
+ :non_match => Factory.string
148
+ }
149
+
150
+ @match_area = Factory::Area.saved_model({
151
+ :name => "#{@params[:match_start]}_#{Factory.string}_#{@params[:match_end]}"
152
+ })
153
+ @other_match_area = Factory::Area.saved_model({
154
+ :name => "#{@params[:match_start]}_#{Factory.string}_#{@params[:match_end]}"
155
+ })
156
+ @only_match_start_area = Factory::Area.saved_model({
157
+ :name => "#{@params[:match_start]}_#{Factory.string}"
158
+ })
159
+ @only_other_match_start_area = Factory::Area.saved_model({
160
+ :name => "#{@params[:other_match_start]}_#{Factory.string}"
161
+ })
162
+ @only_match_end_area = Factory::Area.saved_model({
163
+ :name => "#{Factory.string}_#{@params[:match_end]}"
164
+ })
165
+ @non_match_area = Factory::Area.saved_model({
166
+ :name => "#{@params[:match_start]}_#{@params[:non_match]}_#{@params[:match_end]}"
167
+ })
168
+ end
169
+
170
+ end
171
+
172
+ class SetOperatorSystemTests < SetOperatorSetupTests
173
+ desc "query that uses set operators"
174
+ setup do
175
+ @results = SetData.query(@params).results
176
+ end
177
+ subject{ @results }
178
+
179
+ should "have found the matching area data" do
180
+ exp = [@match_area, @other_match_area].map(&:id)
181
+ assert_equal exp, subject.map(&:id)
182
+ end
183
+
184
+ end
185
+
186
+ class SetOperatorFindSystemTests < SetOperatorSetupTests
187
+ desc "find that uses set operators"
188
+ setup do
189
+ @result = SetData.find(@other_match_area.id, @params)
190
+ end
191
+ subject{ @result }
192
+
193
+ should "have found the matching area, user and comment data" do
194
+ assert_equal @other_match_area.id, subject.id
195
+ end
196
+
197
+ end
198
+
199
+ end
@@ -0,0 +1,275 @@
1
+ require 'assert'
2
+ require 'mr'
3
+
4
+ require 'test/support/setup_test_db'
5
+ require 'test/support/factory/area'
6
+ require 'test/support/factory/user'
7
+ require 'test/support/models/area'
8
+ require 'test/support/models/comment'
9
+ require 'test/support/models/user'
10
+
11
+ class WithModelTests < DbTests
12
+ desc "MR with an ActiveRecord model"
13
+ setup do
14
+ @area = Factory::Area.instance_stack.tap(&:create).model
15
+ @user = User.new(:name => "Joe Test", :area => @area)
16
+ end
17
+ subject{ @user }
18
+
19
+ should "allow accessing the record's attributes" do
20
+ assert_nothing_raised do
21
+ subject.name = 'Joe Test'
22
+ subject.number = 12345
23
+ end
24
+
25
+ # check that the attributes were set
26
+ assert_equal 'Joe Test', subject.record.name
27
+ assert_equal 12345, subject.record.number
28
+
29
+ # check that we can read the attributes
30
+ assert_equal 'Joe Test', subject.name
31
+ assert_equal 12345, subject.number
32
+ end
33
+
34
+ should "allow reading previous values for a record's attribute" do
35
+ assert_nil subject.name_was
36
+ subject.name = 'Test'
37
+ assert_nil subject.name_was
38
+ subject.save
39
+ assert_equal 'Test', subject.name_was
40
+ subject.name = 'New Test'
41
+ assert_equal 'Test', subject.name_was
42
+ end
43
+
44
+ should "allow mass setting and reading the record's attributes" do
45
+ assert_nothing_raised do
46
+ subject.fields = {
47
+ :name => 'Joe Test',
48
+ :number => 12345,
49
+ }
50
+ end
51
+
52
+ # check that the attributes were set
53
+ assert_equal 'Joe Test', subject.record.name
54
+ assert_equal 12345, subject.record.number
55
+
56
+ expected = {
57
+ 'id' => nil,
58
+ 'name' => 'Joe Test',
59
+ 'number' => 12345,
60
+ 'salary' => nil,
61
+ 'started_on' => nil,
62
+ 'dob' => nil,
63
+ 'area_id' => @area.id,
64
+ }
65
+ assert_equal expected, subject.fields
66
+ end
67
+
68
+ should "be able to save and destroy the model" do
69
+ assert_nothing_raised do
70
+ subject.fields = {
71
+ :name => 'Joe Test',
72
+ :number => 12345,
73
+ }
74
+ subject.save
75
+ end
76
+ assert_not subject.destroyed?
77
+ assert UserRecord.exists?(subject.id)
78
+
79
+ assert_nothing_raised do
80
+ subject.destroy
81
+ end
82
+ assert subject.destroyed?
83
+ assert_not UserRecord.exists?(subject.id)
84
+ end
85
+
86
+ end
87
+
88
+ class DetectChangedFieldsTests < WithModelTests
89
+ setup do
90
+ @user = User.new(:area => @area)
91
+ end
92
+
93
+ should "detect when it's fields have changed" do
94
+ assert subject.new?
95
+ assert_not subject.name_changed?
96
+ subject.name = 'Test'
97
+ assert subject.name_changed?
98
+
99
+ subject.save
100
+ assert_not subject.new?
101
+ assert_not subject.name_changed?
102
+ subject.name = 'New Test'
103
+ assert subject.name_changed?
104
+ end
105
+
106
+ end
107
+
108
+ class BelongsToTests < WithModelTests
109
+ desc "using a belongs to association"
110
+ setup do
111
+ @user.area = nil
112
+ @area = Area.new(:name => 'Alpha').tap(&:save)
113
+ end
114
+
115
+ should "be able to read it and write to it" do
116
+ assert_nil subject.area
117
+ assert_nothing_raised do
118
+ subject.area = @area
119
+ end
120
+ assert_equal @area, subject.area
121
+ assert_equal @area.id, subject.area_id
122
+ end
123
+
124
+ end
125
+
126
+ class HasManyTests < WithModelTests
127
+ desc "using a has many association"
128
+ setup do
129
+ @user.save
130
+ @comment = Comment.new(:body => "Test", :parent => @user)
131
+ end
132
+
133
+ should "be able to read it" do
134
+ @comment.save
135
+ assert_equal [ @comment ], subject.comments
136
+ end
137
+
138
+ end
139
+
140
+ class HasOneTests < WithModelTests
141
+ desc "using a has one association"
142
+ setup do
143
+ @user.save
144
+ @image = Image.new(:file_path => "test", :user => @user)
145
+ end
146
+
147
+ should "be able to read it" do
148
+ @image.save
149
+ assert_equal @image, subject.image
150
+ end
151
+
152
+ end
153
+
154
+ class PolymorphicBelongsToTests < WithModelTests
155
+ desc "using a polymorphic belongs to association"
156
+ setup do
157
+ @user.save
158
+ @area = Area.new(:name => 'Alpha')
159
+ @area.save
160
+ @comment = Comment.new(:body => "Test")
161
+ end
162
+ subject{ @comment }
163
+
164
+ should "be able to read it and write to it" do
165
+ assert_nil subject.parent
166
+
167
+ assert_nothing_raised do
168
+ subject.parent = @area
169
+ end
170
+ assert_equal @area, subject.parent
171
+ assert_equal @area.id, subject.parent_id
172
+ assert_equal 'AreaRecord', subject.parent_type
173
+
174
+ assert_nothing_raised do
175
+ subject.parent = @user
176
+ end
177
+ assert_equal @user, subject.parent
178
+ assert_equal @user.id, subject.parent_id
179
+ assert_equal 'UserRecord', subject.parent_type
180
+ end
181
+
182
+ end
183
+
184
+ class QueryTests < WithModelTests
185
+ desc "using a MR::Query"
186
+ setup do
187
+ @users = [*(0..4)].map do |i|
188
+ User.new(:name => "test #{i}", :area => @area).tap(&:save)
189
+ end
190
+ @query = MR::Query.new(User, UserRecord.scoped)
191
+ end
192
+ subject{ @query }
193
+
194
+ should "fetch the results with #results" do
195
+ assert_equal @users.map(&:name), subject.results.map(&:name)
196
+ end
197
+
198
+ should "count the results with #count" do
199
+ assert_equal 5, subject.count
200
+ end
201
+
202
+ end
203
+
204
+ class PagedQueryTests < QueryTests
205
+ setup do
206
+ @paged_query = @query.paged(1, 3)
207
+ end
208
+ subject{ @paged_query }
209
+
210
+ should "fetch the paged results with #results" do
211
+ assert_equal @users[0, 3], subject.results
212
+
213
+ paged_query = @query.paged(2, 3)
214
+ assert_equal @users[3, 2], paged_query.results
215
+ end
216
+
217
+ should "count the paged results with #count" do
218
+ assert_equal 3, subject.count
219
+
220
+ paged_query = @query.paged(2, 3)
221
+ assert_equal 2, paged_query.count
222
+ end
223
+
224
+ should "count the total number of results with #total_count" do
225
+ assert_equal 5, subject.total_count
226
+ end
227
+
228
+ end
229
+
230
+ class FinderTests < WithModelTests
231
+ setup do
232
+ @users = [*1..2].map do |i|
233
+ Factory::User.instance(:area => @area).tap(&:save)
234
+ end
235
+ end
236
+
237
+ should "allow fetching a single user with find" do
238
+ assert_equal @users.first, User.find(@users.first.id)
239
+
240
+ assert_raises(ActiveRecord::RecordNotFound) do
241
+ User.find(1000)
242
+ end
243
+ end
244
+
245
+ should "allow fetching a all users with all" do
246
+ assert_equal @users, User.all
247
+ end
248
+
249
+ end
250
+
251
+ class InvalidTests < WithModelTests
252
+ desc "when saving an invalid model"
253
+ setup do
254
+ @area = Area.new(ValidAreaRecord.new)
255
+ end
256
+ subject{ @area }
257
+
258
+ should "raise a InvalidModel exception with the ActiveRecord error messages" do
259
+ exception = nil
260
+ begin
261
+ subject.save
262
+ rescue Exception => exception
263
+ end
264
+
265
+ assert_instance_of MR::Model::InvalidError, exception
266
+ assert_equal [ "can't be blank" ], exception.errors[:name]
267
+ assert_includes ":name can't be blank", exception.message
268
+ end
269
+
270
+ should "return the ActiveRecord's error messages with errors" do
271
+ subject.valid?
272
+ assert_equal [ "can't be blank" ], subject.errors[:name]
273
+ end
274
+
275
+ end