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,106 @@
1
+ require 'assert'
2
+ require 'mr/fake_record'
3
+
4
+ require 'much-plugin'
5
+
6
+ module MR::FakeRecord
7
+
8
+ class UnitTests < Assert::Context
9
+ desc "MR::FakeRecord"
10
+ setup do
11
+ @module = MR::FakeRecord
12
+ end
13
+ subject{ @module }
14
+
15
+ should "use much-plugin" do
16
+ assert_includes MuchPlugin, subject
17
+ end
18
+
19
+ should "extend the persistence transaction methods mixin" do
20
+ metaclass = class << subject; self; end
21
+ assert_includes MR::FakeRecord::Persistence::TransactionMethods, metaclass
22
+ end
23
+
24
+ end
25
+
26
+ class MixedInTests < UnitTests
27
+ desc "when mixed in"
28
+ setup do
29
+ @fake_record_class = Class.new do
30
+ include MR::FakeRecord
31
+ attribute :name, :string
32
+ attribute :active, :boolean
33
+ end
34
+ end
35
+ subject{ @fake_record_class }
36
+
37
+ should have_imeths :model_class
38
+
39
+ should "be an MR record" do
40
+ assert_includes MR::Record, subject
41
+ end
42
+
43
+ should "include the associations, attributes and persistence mixins" do
44
+ assert_includes MR::FakeRecord::Associations, subject
45
+ assert_includes MR::FakeRecord::Attributes, subject
46
+ assert_includes MR::FakeRecord::Persistence, subject
47
+ end
48
+
49
+ should "allow reading and writing it's model class using `model_class`" do
50
+ assert_nil subject.model_class
51
+ model_class = Class.new
52
+ subject.model_class(model_class)
53
+ assert_equal model_class, subject.model_class
54
+ end
55
+
56
+ should "allow passing attributes to it's initialize" do
57
+ fake_record = subject.new(:name => 'test')
58
+ assert_equal 'test', fake_record.name
59
+ end
60
+
61
+ end
62
+
63
+ class InitTests < MixedInTests
64
+ desc "and init"
65
+ setup do
66
+ @fake_record = @fake_record_class.new({
67
+ :name => 'test',
68
+ :active => true
69
+ })
70
+ @fake_record.save!
71
+ end
72
+ subject{ @fake_record }
73
+
74
+ should have_imeths :==, :eql?, :hash, :inspect
75
+
76
+ should "return a readable inspect" do
77
+ object_hex = (subject.object_id << 1).to_s(16)
78
+ expected = "#<#{subject.class}:0x#{object_hex} @active=true " \
79
+ "@id=#{subject.id} @name=\"test\">"
80
+ assert_equal expected, subject.inspect
81
+ end
82
+
83
+ should "be comparable" do
84
+ same_fake_record = @fake_record_class.new(:id => @fake_record.id)
85
+ assert_equal same_fake_record, subject
86
+ other_fake_record = @fake_record_class.new.tap(&:save!)
87
+ assert_not_equal other_fake_record, subject
88
+ end
89
+
90
+ should "demeter its fixnum hash value to its id" do
91
+ assert_equal subject.id.hash, subject.hash
92
+ end
93
+
94
+ should "ensure it's attribute changed methods work after an empty save" do
95
+ assert_not_nil subject.name
96
+ assert_true subject.active
97
+ subject.save! # empty save, nothing was changed
98
+ subject.name = nil # set a previously set attribute to `nil`
99
+ subject.active = true # set it to what it previous was
100
+ assert subject.name_changed?
101
+ assert_not subject.active_changed?
102
+ end
103
+
104
+ end
105
+
106
+ end
@@ -0,0 +1,75 @@
1
+ require 'assert'
2
+ require 'mr/json_field/fake_record'
3
+
4
+ require 'much-plugin'
5
+ require 'mr/json_field'
6
+ require 'mr/model'
7
+
8
+ module MR::JsonField::FakeRecord
9
+
10
+ class UnitTests < Assert::Context
11
+ desc "MR::JsonField::FakeRecord"
12
+ subject{ MR::JsonField::FakeRecord }
13
+
14
+ should "use much-plugin" do
15
+ assert_includes MuchPlugin, subject
16
+ end
17
+
18
+ end
19
+
20
+ class MixinTests < UnitTests
21
+ desc "when mixed in"
22
+ setup do
23
+ @fake_record_class = Class.new do
24
+ include MR::JsonField::FakeRecord
25
+ attribute :hash_data_json, :text
26
+ attribute :array_data_json, :text
27
+ end
28
+ end
29
+ subject{ @fake_record_class }
30
+
31
+ end
32
+
33
+ class InitTests < MixinTests
34
+ desc "and init"
35
+ setup do
36
+ @model_class = Class.new do
37
+ include MR::Model
38
+ field_accessor :hash_data_json, :array_data_json
39
+
40
+ include MR::JsonField
41
+ json_field :hash_data
42
+ json_field :array_data
43
+ end
44
+ @fake_record_class.model_class(@model_class)
45
+
46
+ @fake_record = @fake_record_class.new
47
+ @model = @fake_record.model
48
+ end
49
+ subject{ @fake_record }
50
+
51
+ should "sync all of its json fields on save" do
52
+ @model.hash_data = { Factory.string => Factory.string }
53
+ @model.array_data = Factory.integer(3).times.map{ Factory.string }
54
+
55
+ # since we used the writer the fields and their source should be equal
56
+ assert_equal @model.hash_data, MR::JsonField.decode(subject.hash_data_json)
57
+ assert_equal @model.array_data, MR::JsonField.decode(subject.array_data_json)
58
+
59
+ @model.hash_data[Factory.string] = Factory.string
60
+ @model.array_data << Factory.string
61
+ # since we modified the fields and didn't use the writer, their source
62
+ # should not be equal
63
+ assert_not_equal @model.hash_data, MR::JsonField.decode(subject.hash_data_json)
64
+ assert_not_equal @model.array_data, MR::JsonField.decode(subject.array_data_json)
65
+
66
+ subject.save!
67
+
68
+ # now that the callback has been run they should be equal once again
69
+ assert_equal @model.hash_data, MR::JsonField.decode(subject.hash_data_json)
70
+ assert_equal @model.array_data, MR::JsonField.decode(subject.array_data_json)
71
+ end
72
+
73
+ end
74
+
75
+ end
@@ -0,0 +1,80 @@
1
+ require 'assert'
2
+ require 'mr/json_field/record'
3
+
4
+ require 'ardb/record_spy'
5
+ require 'much-plugin'
6
+ require 'mr/json_field'
7
+ require 'mr/model'
8
+
9
+ module MR::JsonField::Record
10
+
11
+ class UnitTests < Assert::Context
12
+ desc "MR::JsonField::Record"
13
+ subject{ MR::JsonField::Record }
14
+
15
+ should "use much-plugin" do
16
+ assert_includes MuchPlugin, subject
17
+ end
18
+
19
+ end
20
+
21
+ class MixinTests < UnitTests
22
+ desc "when mixed in"
23
+ setup do
24
+ @record_class = Ardb::RecordSpy.new do
25
+ include MR::JsonField::Record
26
+ attr_accessor :hash_data_json, :array_data_json
27
+ end
28
+ end
29
+ subject{ @record_class }
30
+
31
+ should "add a before save callback" do
32
+ callback = subject.callbacks.find{ |c| c.type == :before_save }
33
+ assert_equal :json_field_sync_all_json_fields_on_save, callback.args.first
34
+ end
35
+
36
+ end
37
+
38
+ class InitTests < MixinTests
39
+ desc "and init"
40
+ setup do
41
+ @model_class = Class.new do
42
+ include MR::Model
43
+ field_accessor :hash_data_json, :array_data_json
44
+
45
+ include MR::JsonField
46
+ json_field :hash_data
47
+ json_field :array_data
48
+ end
49
+ @record_class.model_class = @model_class
50
+
51
+ @record = @record_class.new
52
+ @model = @record.model
53
+ end
54
+ subject{ @record }
55
+
56
+ should "sync all of its json fields on save" do
57
+ @model.hash_data = { Factory.string => Factory.string }
58
+ @model.array_data = Factory.integer(3).times.map{ Factory.string }
59
+
60
+ # since we used the writer the fields and their source should be equal
61
+ assert_equal @model.hash_data, MR::JsonField.decode(subject.hash_data_json)
62
+ assert_equal @model.array_data, MR::JsonField.decode(subject.array_data_json)
63
+
64
+ @model.hash_data[Factory.string] = Factory.string
65
+ @model.array_data << Factory.string
66
+ # since we modified the fields and didn't use the writer, their source
67
+ # should not be equal
68
+ assert_not_equal @model.hash_data, MR::JsonField.decode(subject.hash_data_json)
69
+ assert_not_equal @model.array_data, MR::JsonField.decode(subject.array_data_json)
70
+
71
+ subject.instance_eval{ json_field_sync_all_json_fields_on_save }
72
+
73
+ # now that the callback has been run they should be equal once again
74
+ assert_equal @model.hash_data, MR::JsonField.decode(subject.hash_data_json)
75
+ assert_equal @model.array_data, MR::JsonField.decode(subject.array_data_json)
76
+ end
77
+
78
+ end
79
+
80
+ end
@@ -0,0 +1,302 @@
1
+ require 'assert'
2
+ require 'mr/json_field'
3
+
4
+ require 'much-plugin'
5
+
6
+ module MR::JsonField
7
+
8
+ class UnitTests < Assert::Context
9
+ desc "MR::JsonField"
10
+ setup do
11
+ @module = MR::JsonField
12
+
13
+ @orig_encoder = @module.encoder
14
+ @orig_decoder = @module.decoder
15
+ end
16
+ teardown do
17
+ @module.encoder = @orig_encoder
18
+ @module.decoder = @orig_decoder
19
+ end
20
+ subject{ @module }
21
+
22
+ should have_imeths :encoder, :encoder=
23
+ should have_imeths :decoder, :decoder=
24
+ should have_imeths :encode, :decode
25
+
26
+ should "use much-plugin" do
27
+ assert_includes MuchPlugin, subject
28
+ end
29
+
30
+ should "know its default encoder and decoder" do
31
+ value = { Factory.string => Factory.string }
32
+
33
+ exp = JSON.dump(value)
34
+ assert_equal exp, DEFAULT_ENCODER.call(value)
35
+
36
+ encoded_value = exp
37
+ exp = JSON.load(encoded_value)
38
+ assert_equal exp, DEFAULT_DECODER.call(encoded_value)
39
+ end
40
+
41
+ should "default its encoder and decoder" do
42
+ assert_equal DEFAULT_ENCODER, subject.encoder
43
+ assert_equal DEFAULT_DECODER, subject.decoder
44
+ end
45
+
46
+ should "use its encoder/decoder when encoding/decoding" do
47
+ value = { Factory.string => Factory.string }
48
+
49
+ exp = subject.encoder.call(value)
50
+ assert_equal exp, subject.encode(value)
51
+
52
+ encoded_value = exp
53
+ exp = subject.decoder.call(encoded_value)
54
+ assert_equal exp, subject.decode(encoded_value)
55
+ end
56
+
57
+ should "allow specifying a custom encoder/decoder" do
58
+ subject.encoder = proc{ |v| v.to_s }
59
+ subject.decoder = proc{ |v| v.to_i }
60
+
61
+ value = Factory.integer
62
+ assert_equal value.to_s, subject.encode(value)
63
+
64
+ value = Factory.integer.to_s
65
+ assert_equal value.to_i, subject.decode(value)
66
+ end
67
+
68
+ end
69
+
70
+ class MixedInSetupTests < UnitTests
71
+ setup do
72
+ @json_field_class = Class.new do
73
+ include MR::JsonField
74
+ attr_accessor :test_data_json, :custom_data_source
75
+ end
76
+ end
77
+
78
+ end
79
+
80
+ class MixedInTests < MixedInSetupTests
81
+ desc "when mixed in"
82
+ subject{ @json_field_class }
83
+
84
+ should have_imeths :json_field, :json_field_reader, :json_field_writer
85
+ should have_imeths :json_field_readers, :json_field_writers
86
+ should have_imeths :json_field_accessors, :json_field_source_fields
87
+
88
+ should "not have any json field accessors or source fields by default" do
89
+ assert_equal [], subject.json_field_readers
90
+ assert_equal [], subject.json_field_writers
91
+ assert_equal [], subject.json_field_accessors
92
+ assert_equal [], subject.json_field_source_fields
93
+ end
94
+
95
+ should "allow adding a json field reader" do
96
+ subject.json_field_reader 'test_data'
97
+ instance = subject.new
98
+
99
+ assert_respond_to 'test_data', instance
100
+ assert_equal ['test_data'], subject.json_field_readers
101
+ assert_equal ['test_data_json'], subject.json_field_source_fields
102
+ assert_equal [], subject.json_field_writers
103
+ assert_equal [], subject.json_field_accessors
104
+ end
105
+
106
+ should "allow adding a json field reader with a custom source" do
107
+ subject.json_field_reader 'custom_data', :source => 'custom_data_source'
108
+ instance = subject.new
109
+
110
+ assert_respond_to 'custom_data', instance
111
+ assert_equal ['custom_data'], subject.json_field_readers
112
+ assert_equal ['custom_data_source'], subject.json_field_source_fields
113
+ assert_equal [], subject.json_field_writers
114
+ assert_equal [], subject.json_field_accessors
115
+ end
116
+
117
+ should "allow adding a json field writer" do
118
+ subject.json_field_writer 'test_data'
119
+ instance = subject.new
120
+
121
+ assert_respond_to 'test_data=', instance
122
+ assert_equal ['test_data'], subject.json_field_writers
123
+ assert_equal ['test_data_json'], subject.json_field_source_fields
124
+ assert_equal [], subject.json_field_readers
125
+ assert_equal [], subject.json_field_accessors
126
+ end
127
+
128
+ should "allow adding a json field writer with a custom source" do
129
+ subject.json_field_writer 'custom_data', :source => 'custom_data_source'
130
+ instance = subject.new
131
+
132
+ assert_respond_to 'custom_data=', instance
133
+ assert_equal ['custom_data'], subject.json_field_writers
134
+ assert_equal ['custom_data_source'], subject.json_field_source_fields
135
+ assert_equal [], subject.json_field_readers
136
+ assert_equal [], subject.json_field_accessors
137
+ end
138
+
139
+ should "allow adding a json field accessor" do
140
+ subject.json_field 'test_data'
141
+ instance = subject.new
142
+
143
+ assert_respond_to 'test_data', instance
144
+ assert_respond_to 'test_data=', instance
145
+ exp = ['test_data']
146
+ assert_equal exp, subject.json_field_readers
147
+ assert_equal exp, subject.json_field_writers
148
+ assert_equal exp, subject.json_field_accessors
149
+ assert_equal ['test_data_json'], subject.json_field_source_fields
150
+ end
151
+
152
+ should "allow adding a json field accessor with a custom source" do
153
+ subject.json_field 'custom_data', :source => 'custom_data_source'
154
+ instance = subject.new
155
+
156
+ assert_respond_to 'custom_data', instance
157
+ assert_respond_to 'custom_data=', instance
158
+ exp = ['custom_data']
159
+ assert_equal exp, subject.json_field_readers
160
+ assert_equal exp, subject.json_field_writers
161
+ assert_equal exp, subject.json_field_accessors
162
+ assert_equal ['custom_data_source'], subject.json_field_source_fields
163
+ end
164
+
165
+ should "know it has an accessor if a reader and writer are added separately" do
166
+ subject.json_field_reader 'test_data'
167
+ subject.json_field_writer 'test_data'
168
+ instance = subject.new
169
+
170
+ assert_equal ['test_data'], subject.json_field_accessors
171
+ assert_equal ['test_data_json'], subject.json_field_source_fields
172
+ end
173
+
174
+ should "allow using symbols when adding json fields" do
175
+ subject.json_field :test_data
176
+ subject.json_field_reader :custom_data, :source => :custom_data_source
177
+ subject.json_field_writer :custom_data, :source => :custom_data_source
178
+ instance = subject.new
179
+
180
+ assert_respond_to :test_data, instance
181
+ assert_respond_to :test_data=, instance
182
+ assert_respond_to :custom_data, instance
183
+ assert_respond_to :custom_data=, instance
184
+ exp = ['test_data', 'custom_data']
185
+ assert_equal exp, subject.json_field_readers
186
+ assert_equal exp, subject.json_field_writers
187
+ assert_equal exp, subject.json_field_accessors
188
+ exp = ['test_data_json', 'custom_data_source']
189
+ assert_equal exp, subject.json_field_source_fields
190
+ end
191
+
192
+ should "error if the source matches the field name" do
193
+ name = Factory.string
194
+ assert_raises(ArgumentError) do
195
+ subject.json_field_reader(name, :source => name)
196
+ end
197
+ assert_raises(ArgumentError) do
198
+ subject.json_field_writer(name, :source => name)
199
+ end
200
+ assert_raises(ArgumentError) do
201
+ subject.json_field(name, :source => name)
202
+ end
203
+ end
204
+
205
+ end
206
+
207
+ class InitTests < MixedInTests
208
+ desc "and init"
209
+ setup do
210
+ @value = [
211
+ Factory.string,
212
+ Factory.integer,
213
+ Factory.boolean,
214
+ Factory.integer(3).times{ Factory.integer },
215
+ { Factory.string => Factory.string }
216
+ ].sample
217
+
218
+ @json_field_class.json_field :test_data
219
+ @json_field_class.json_field :custom_data, :source => :custom_data_source
220
+
221
+ @instance = @json_field_class.new
222
+ end
223
+ subject{ @instance }
224
+
225
+ should "allow reading/writing json fields" do
226
+ assert_nil subject.test_data
227
+ assert_nil subject.test_data_json
228
+ assert_nil subject.custom_data
229
+ assert_nil subject.custom_data_source
230
+
231
+ subject.test_data = @value
232
+ subject.custom_data = @value
233
+
234
+ exp = MR::JsonField.encode(@value)
235
+ assert_equal exp, subject.test_data_json
236
+ assert_equal exp, subject.custom_data_source
237
+ assert_equal @value, subject.test_data
238
+ assert_equal @value, subject.custom_data
239
+ end
240
+
241
+ should "cache read/written values" do
242
+ subject.test_data = @value
243
+ subject.custom_data = @value
244
+
245
+ result = subject.test_data
246
+ assert_same result, subject.test_data
247
+ result = subject.custom_data
248
+ assert_same result, subject.custom_data
249
+ end
250
+
251
+ should "allow reading/writing `nil` values" do
252
+ subject.test_data = @value
253
+ subject.custom_data = @value
254
+
255
+ assert_nothing_raised{ subject.test_data = nil }
256
+ assert_nil subject.test_data
257
+ assert_nothing_raised{ subject.custom_data = nil }
258
+ assert_nil subject.custom_data
259
+ end
260
+
261
+ should "raise an invalid json error when reading invalid JSON" do
262
+ subject.test_data_json = Factory.string
263
+ subject.custom_data_source = Factory.string
264
+
265
+ assert_raises(InvalidJSONError){ subject.test_data }
266
+ assert_raises(InvalidJSONError){ subject.custom_data }
267
+ end
268
+
269
+ should "raise an invalid json error when writing invalid JSON" do
270
+ Assert.stub(MR::JsonField.encoder, :call){ raise RuntimeError }
271
+
272
+ assert_raises(InvalidJSONError){ subject.test_data = Factory.string }
273
+ assert_raises(InvalidJSONError){ subject.custom_data = Factory.string }
274
+ end
275
+
276
+ end
277
+
278
+ class TestHelpersTests < MixedInSetupTests
279
+ include MR::JsonField::TestHelpers
280
+
281
+ desc "TestHelpers"
282
+ setup do
283
+ @json_field_class.json_field :test_data
284
+ @json_field_class.json_field :custom_data, :source => :custom_data_source
285
+
286
+ @instance = @json_field_class.new
287
+ end
288
+ subject{ @instance }
289
+
290
+ should "provide helpers for testing that a class has json fields" do
291
+ assert_json_field subject, :test_data
292
+ assert_json_field_reader subject, :test_data
293
+ assert_json_field_writer subject, :test_data
294
+
295
+ assert_json_field subject, :custom_data, :source => :custom_data_source
296
+ assert_json_field_reader subject, :custom_data, :source => :custom_data_source
297
+ assert_json_field_writer subject, :custom_data, :source => :custom_data_source
298
+ end
299
+
300
+ end
301
+
302
+ end