mr 0.35.2

Sign up to get free protection for your applications and to get access to all the features.
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,114 @@
1
+ require 'assert'
2
+ require 'mr/model/persistence'
3
+
4
+ require 'much-plugin'
5
+ require 'mr/fake_record'
6
+
7
+ module MR::Model::Persistence
8
+
9
+ class UnitTests < Assert::Context
10
+ desc "MR::Model::Persistence"
11
+ setup do
12
+ @model_class = Class.new do
13
+ include MR::Model::Persistence
14
+ record_class FakeTestRecord
15
+ def initialize(record); set_record record; end
16
+ end
17
+ end
18
+ subject{ @model_class }
19
+
20
+ should have_imeths :transaction
21
+
22
+ should "use much-plugin" do
23
+ assert_includes MuchPlugin, MR::Model::Persistence
24
+ end
25
+
26
+ should "call the record class's transaction method using `transaction`" do
27
+ yielded = nil
28
+ subject.transaction{ yielded = true }
29
+ assert yielded
30
+ end
31
+
32
+ end
33
+
34
+ class InstanceTests < UnitTests
35
+ desc "for a model instance"
36
+ setup do
37
+ @record = FakeTestRecord.new
38
+ @model = @model_class.new(@record)
39
+ end
40
+ subject{ @model }
41
+
42
+ should have_imeths :save, :destroy
43
+ should have_imeths :transaction
44
+ should have_imeths :errors, :valid?
45
+ should have_imeths :new?, :destroyed?
46
+
47
+ should "save the record using `save`" do
48
+ assert @record.new_record?
49
+ subject.save
50
+ assert_not @record.new_record?
51
+ end
52
+
53
+ should "destroy the record using `destroy`" do
54
+ assert_not @record.destroyed?
55
+ subject.destroy
56
+ assert @record.destroyed?
57
+ end
58
+
59
+ should "call the record's transaction method using `transaction`" do
60
+ yielded = nil
61
+ subject.transaction{ yielded = true }
62
+ assert yielded
63
+ end
64
+
65
+ should "return the record's error messages using `errors`" do
66
+ @record.errors.add(:name, 'something went wrong')
67
+ assert_equal @record.errors.messages, subject.errors
68
+ end
69
+
70
+ should "call the record's valid method using `valid?`" do
71
+ assert_equal true, subject.valid?
72
+ @record.errors.add(:name, 'something went wrong')
73
+ assert_equal false, subject.valid?
74
+ end
75
+
76
+ should "call the record's new record method using `new?`" do
77
+ assert_equal true, subject.new?
78
+ @record.save!
79
+ assert_equal false, subject.new?
80
+ end
81
+
82
+ should "call the record's destroyed method using `destroyed?`" do
83
+ @record.save!
84
+ assert_equal false, subject.destroyed?
85
+ @record.destroy
86
+ assert_equal true, subject.destroyed?
87
+ end
88
+
89
+ should "raise an invalid error when calling `save` with an invalid record" do
90
+ @record.errors.add(:name, 'something went wrong')
91
+ @record.errors.add(:name, 'another thing failed')
92
+ @record.errors.add(:active, 'is not valid')
93
+
94
+ exception = nil
95
+ begin; subject.save; rescue StandardError => exception; end
96
+
97
+ assert_instance_of MR::Model::InvalidError, exception
98
+ assert_equal subject.errors, exception.errors
99
+ description = subject.errors.map do |(attribute, messages)|
100
+ messages.map{|message| "#{attribute.inspect} #{message}" }
101
+ end.sort.join(', ')
102
+ expected = "Invalid #{subject.class} couldn't be saved: #{description}"
103
+ assert_equal expected, exception.message
104
+ expected = "test/unit/model/persistence_tests.rb"
105
+ assert_match expected, exception.backtrace.first
106
+ end
107
+
108
+ end
109
+
110
+ class FakeTestRecord
111
+ include MR::FakeRecord
112
+ end
113
+
114
+ end
@@ -0,0 +1,137 @@
1
+ require 'assert'
2
+ require 'mr/model'
3
+
4
+ require 'much-plugin'
5
+ require 'mr/fake_record'
6
+
7
+ module MR::Model
8
+
9
+ class UnitTests < Assert::Context
10
+ desc "MR::Model"
11
+ setup do
12
+ @model_class = Class.new do
13
+ include MR::Model
14
+ record_class FakeTestRecord
15
+ field_reader :id
16
+ field_accessor :name, :active
17
+ end
18
+ end
19
+ subject{ @model_class }
20
+
21
+ should have_imeths :find, :all
22
+
23
+ should "use much-plugin" do
24
+ assert_includes MuchPlugin, MR::Model
25
+ end
26
+
27
+ should "include the configuration, fields, associations and persistence mixins" do
28
+ assert_includes MR::Model::Configuration, subject
29
+ assert_includes MR::Model::Fields, subject
30
+ assert_includes MR::Model::Associations, subject
31
+ assert_includes MR::Model::Persistence, subject
32
+ end
33
+
34
+ should "allow passing a record to it's initialize" do
35
+ fake_record = FakeTestRecord.new(:name => 'test')
36
+ model = subject.new(fake_record)
37
+ assert_equal 'test', model.name
38
+ end
39
+
40
+ should "allow passing fields to it's initialize" do
41
+ model = subject.new(:name => 'test')
42
+ assert_equal 'test', model.name
43
+ end
44
+
45
+ should "allow passing both a record and fields to it's initialize" do
46
+ fake_record = FakeTestRecord.new(:name => 'test1')
47
+ model = subject.new(fake_record, :name => 'test2')
48
+ assert_equal 'test2', model.name
49
+ assert_equal 'test2', fake_record.name
50
+ end
51
+
52
+ end
53
+
54
+ class WithRecordClassSpyTests < UnitTests
55
+ setup do
56
+ @fake_records = [*1..2].map{ FakeTestRecord.new.tap(&:save!) }
57
+ RecordClassSpy.fake_records = @fake_records
58
+ @model_class.record_class RecordClassSpy
59
+ end
60
+ teardown do
61
+ RecordClassSpy.fake_records = nil
62
+ end
63
+
64
+ should "call find on the record class using `find`" do
65
+ fake_record = @fake_records.first
66
+ model = subject.find(fake_record.id)
67
+ assert_equal subject.new(fake_record), model
68
+ end
69
+
70
+ should "call all on the record class and map building instances using `all`" do
71
+ exp = @fake_records.map{ |fake_record| subject.new(fake_record) }
72
+ assert_equal exp, subject.all
73
+ end
74
+
75
+ end
76
+
77
+ class InstanceTests < UnitTests
78
+ desc "for a model instance"
79
+ setup do
80
+ @fake_record = FakeTestRecord.new
81
+ @model = @model_class.new(@fake_record, :name => 'test', :active => true)
82
+ @model.save
83
+ end
84
+ subject{ @model }
85
+
86
+ should have_imeths :==, :eql?, :hash, :inspect
87
+
88
+ should "return a readable inspect" do
89
+ object_hex = (subject.object_id << 1).to_s(16)
90
+ expected = "#<#{subject.class}:0x#{object_hex} @active=true " \
91
+ "@id=#{subject.id} @name=\"test\">"
92
+ assert_equal expected, subject.inspect
93
+ end
94
+
95
+ should "be comparable using `==`" do
96
+ same_model = @model_class.new(@fake_record)
97
+ assert_equal same_model, subject
98
+ other_model = @model_class.new.tap(&:save)
99
+ assert_not_equal other_model, subject
100
+ end
101
+
102
+ should "be comparable using `eql?`" do
103
+ same_model = @model_class.new(@fake_record)
104
+ assert_true subject.eql?(same_model)
105
+ other_model = @model_class.new.tap(&:save)
106
+ assert_false subject.eql?(other_model)
107
+ end
108
+
109
+ should "demeter its fixnum hash value to its record" do
110
+ assert_equal @fake_record.hash, subject.hash
111
+ end
112
+
113
+ end
114
+
115
+ class FakeTestRecord
116
+ include MR::FakeRecord
117
+ attribute :name, :string
118
+ attribute :active, :boolean
119
+ end
120
+
121
+ class RecordClassSpy
122
+ include MR::Record
123
+
124
+ def self.fake_records=(values)
125
+ @fake_records = values
126
+ end
127
+
128
+ def self.find(id)
129
+ @fake_records.detect{ |fake_record| fake_record.id == id }
130
+ end
131
+
132
+ def self.all
133
+ @fake_records
134
+ end
135
+ end
136
+
137
+ end
@@ -0,0 +1,300 @@
1
+ require 'assert'
2
+ require 'mr/query'
3
+
4
+ require 'ardb/relation_spy'
5
+ require 'mr/fake_record'
6
+ require 'mr/model'
7
+
8
+ class MR::Query
9
+
10
+ class UnitTests < Assert::Context
11
+ desc "MR::Query"
12
+ setup do
13
+ @relation = FakeTestRecord.scoped
14
+ @relation.results = [
15
+ FakeTestRecord.new(:id => 1),
16
+ FakeTestRecord.new(:id => 2)
17
+ ]
18
+ @model_class = FakeTestModel
19
+
20
+ @count_relation_built_with = nil
21
+ @count_relation = nil
22
+ @count_called = false
23
+ Assert.stub(CountRelation, :new) do |*args|
24
+ @count_relation_built_with = args
25
+ @count_relation = Assert.stub_send(CountRelation, :new, *args)
26
+ Assert.stub(@count_relation, :count) do
27
+ @count_called = true
28
+ Assert.stub_send(@count_relation, :count)
29
+ end
30
+ @count_relation
31
+ end
32
+
33
+ @query = MR::Query.new(FakeTestModel, @relation)
34
+ end
35
+ subject{ @query }
36
+
37
+ should have_readers :model_class, :relation
38
+ should have_imeths :results, :results!, :first, :first!, :count, :count!
39
+
40
+ should "know its results" do
41
+ results = subject.results
42
+ assert_equal @relation.results.map{ |r| @model_class.new(r) }, results
43
+ assert_same results, subject.results
44
+ end
45
+
46
+ should "allow re-caching its results" do
47
+ results = subject.results
48
+ assert_same results, subject.results
49
+
50
+ new_results = subject.results!
51
+ assert_not_same results, new_results
52
+ assert_same new_results, subject.results
53
+
54
+ assert_not_same new_results, subject.results!
55
+ end
56
+
57
+ should "know its first result" do
58
+ result = subject.first
59
+ assert_equal @model_class.new(@relation.results.first), result
60
+ assert_same result, subject.first
61
+ end
62
+
63
+ should "return `nil` for its first result if there are no results" do
64
+ @relation.results = []
65
+ assert_nil subject.first
66
+ end
67
+
68
+ should "allow re-caching its first result" do
69
+ result = subject.first
70
+ assert_same result, subject.first
71
+
72
+ new_result = subject.first!
73
+ assert_not_same result, new_result
74
+ assert_same new_result, subject.first
75
+
76
+ assert_not_same new_result, subject.first!
77
+ end
78
+
79
+ should "know how to run a count query to get its count" do
80
+ assert_equal 2, subject.count
81
+ assert_equal [@relation], @count_relation_built_with
82
+ assert_true @count_called
83
+
84
+ # test that it caches the count, a count relation isn't rebuilt and count
85
+ # isn't called
86
+ @count_relation_built_with = nil
87
+ @count_called = false
88
+ assert_equal 2, subject.count
89
+ assert_nil @count_relation_built_with
90
+ assert_false @count_called
91
+ end
92
+
93
+ should "allow re-caching its count" do
94
+ subject.count
95
+ assert_equal [@relation], @count_relation_built_with
96
+
97
+ @count_relation_built_with = nil
98
+ @count_called = false
99
+ subject.count!
100
+ assert_nil @count_relation_built_with
101
+ assert_true @count_called
102
+ end
103
+
104
+ should "know how to build a paged query" do
105
+ paged_query = subject.paged(1, 10)
106
+
107
+ assert_instance_of MR::PagedQuery, paged_query
108
+ assert_equal 1, paged_query.page_num
109
+ assert_equal 10, paged_query.page_size
110
+ end
111
+
112
+ end
113
+
114
+ class PagedQueryTests < UnitTests
115
+ desc "MR::PagedQuery"
116
+ setup do
117
+ @unpaged_relation = @relation.dup
118
+ @paged_query_class = MR::PagedQuery
119
+ @paged_query = @paged_query_class.new(@query, 1, 1)
120
+ end
121
+ subject{ @paged_query }
122
+
123
+ should have_readers :page_num, :page_size, :page_offset
124
+ should have_imeths :total_count, :total_count!
125
+ should have_imeths :has_next_page?, :is_last_page?
126
+
127
+ should "be an mr query" do
128
+ assert_kind_of MR::Query, subject
129
+ end
130
+
131
+ should "default its page number and page size" do
132
+ paged_query = @paged_query_class.new(@query)
133
+
134
+ assert_equal 1, paged_query.page_num
135
+ assert_equal 25, paged_query.page_size
136
+ end
137
+
138
+ should "not allow invalid page numbers or page size values" do
139
+ paged_query = @paged_query_class.new(@query, -1, -10)
140
+
141
+ assert_equal 1, paged_query.page_num
142
+ assert_equal 25, paged_query.page_size
143
+
144
+ paged_query = @paged_query_class.new(@query, 'a', 10.4)
145
+
146
+ # 'a'.to_i is 0, thus it forces it to 1
147
+ assert_equal 1, paged_query.page_num
148
+ # 10.4.to_i is 10, which is valid
149
+ assert_equal 10.4.to_i, paged_query.page_size
150
+ end
151
+
152
+ should "correctly calculate limits and offsets" do
153
+ paged_query = @paged_query_class.new(@query, 1, 10)
154
+
155
+ assert_equal 0, @relation.offset_value
156
+ assert_equal 10, @relation.limit_value
157
+
158
+ paged_query = @paged_query_class.new(@query, 5, 7)
159
+
160
+ assert_equal 28, @relation.offset_value
161
+ assert_equal 7, @relation.limit_value
162
+ end
163
+
164
+ should "know its paged results" do
165
+ exp = @relation.results[0, 1].map{ |r| @model_class.new(r) }
166
+ assert_equal exp, subject.results
167
+ end
168
+
169
+ should "know how to run a paged count query to get its count" do
170
+ assert_equal 1, subject.count
171
+ assert_equal [@relation], @count_relation_built_with
172
+ assert_true @count_called
173
+ end
174
+
175
+ should "know how to run an unpaged count query to get its total count" do
176
+ assert_equal 2, subject.total_count
177
+ assert_equal [@unpaged_relation], @count_relation_built_with
178
+ assert_true @count_called
179
+
180
+ # test that it caches the total count, a count relation isn't rebuilt and
181
+ # count isn't called
182
+ @count_relation_built_with = nil
183
+ @count_called = false
184
+ assert_equal 2, subject.total_count
185
+ assert_nil @count_relation_built_with
186
+ assert_false @count_called
187
+ end
188
+
189
+ should "allow re-caching its total count" do
190
+ subject.total_count
191
+ assert_equal [@unpaged_relation], @count_relation_built_with
192
+
193
+ @count_relation_built_with = nil
194
+ @count_called = false
195
+ subject.total_count!
196
+ assert_nil @count_relation_built_with
197
+ assert_true @count_called
198
+ end
199
+
200
+ should "know if it has a next page or is the last page" do
201
+ page_num = Factory.integer(10)
202
+ page_size = Factory.integer(10)
203
+ paged_query = @paged_query_class.new(@query, page_num, page_size)
204
+
205
+ page_end = paged_query.page_offset + page_size
206
+ total_count = Factory.integer(page_size - 1) + page_end
207
+ Assert.stub(paged_query, :total_count){ total_count }
208
+
209
+ assert_true paged_query.has_next_page?
210
+ assert_false paged_query.is_last_page?
211
+
212
+ paged_query = @paged_query_class.new(@query, page_num, page_size)
213
+ total_count = Factory.integer(page_size - 1) + paged_query.page_offset
214
+ Assert.stub(paged_query, :total_count){ total_count }
215
+
216
+ assert_false paged_query.has_next_page?
217
+ assert_true paged_query.is_last_page?
218
+
219
+ paged_query = @paged_query_class.new(@query, page_num, page_size)
220
+ Assert.stub(paged_query, :total_count){ page_end }
221
+
222
+ assert_false paged_query.has_next_page?
223
+ assert_true paged_query.is_last_page?
224
+ end
225
+
226
+ end
227
+
228
+ class CountRelationTests < UnitTests
229
+ desc "CountRelation"
230
+ setup do
231
+ @relation.select('some_table.some_column')
232
+ @relation.where('some_table.some_column = ?', 1)
233
+ @relation.order('some_table.some_column DESC')
234
+ end
235
+ subject{ CountRelation }
236
+
237
+ should "return the relation with emptied select and order values when " \
238
+ "the original relation was not grouped" do
239
+ count_relation = subject.new(@relation)
240
+
241
+ select_expressions = count_relation.applied.select{ |e| e.type == :select }
242
+ assert_true select_expressions.empty?
243
+ order_expressions = count_relation.applied.select{ |e| e.type == :order }
244
+ assert_true order_expressions.empty?
245
+ # still has the where expression
246
+ where_expressions = count_relation.applied.select{ |e| e.type == :where }
247
+ assert_equal 1, where_expressions.size
248
+ end
249
+
250
+ should "return a new relation for counting a subquery of the original " \
251
+ "relation with emptied select and order values when " \
252
+ "the original relation was grouped" do
253
+ @relation.group_values = [ 'table.id' ]
254
+ count_relation = subject.new(@relation)
255
+
256
+ assert_not_equal count_relation.applied, @relation.applied
257
+ assert_equal 1, count_relation.applied.size
258
+
259
+ from_expression = count_relation.applied.first
260
+ assert_equal :from, from_expression.type
261
+
262
+ exp_relation = @relation.except(:select, :order).select('1')
263
+ exp = "(#{exp_relation.to_sql}) AS grouped_records"
264
+ assert_equal [exp], from_expression.args
265
+ end
266
+
267
+ end
268
+
269
+ class RelationSpy < Ardb::RelationSpy
270
+ attr_reader :klass
271
+ attr_accessor :group_values
272
+
273
+ def initialize(klass, *args)
274
+ super(*args)
275
+ @klass = klass
276
+ @group_values = []
277
+ end
278
+
279
+ # this is just a random readable string, it looks like:
280
+ # select(id).where(some_id, 1)
281
+ def to_sql
282
+ @applied.reverse.map{ |e| "#{e.type}(#{e.args.join(", ")})" }.join('.')
283
+ end
284
+
285
+ end
286
+
287
+ class FakeTestRecord
288
+ include MR::FakeRecord
289
+
290
+ def self.scoped
291
+ RelationSpy.new(self)
292
+ end
293
+ end
294
+
295
+ class FakeTestModel
296
+ include MR::Model
297
+ record_class FakeTestRecord
298
+ end
299
+
300
+ end