embedson 0.0.2 → 1.0.1

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.
@@ -0,0 +1,68 @@
1
+ module Embedson
2
+ module Model
3
+ class EmbedsBuilder
4
+ attr_reader :builder, :klass
5
+
6
+ def initialize(builder)
7
+ @builder = builder
8
+ @klass = builder.klass
9
+ end
10
+
11
+ def define
12
+ methods_embeds.each do |meth|
13
+ klass.class_exec builder, &send(meth)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def methods_embeds
20
+ [:writer, :reader, :related_model, :build_related_model]
21
+ end
22
+
23
+ def writer
24
+ proc do |builder|
25
+ define_method("#{builder.field_name}=") do |arg|
26
+ verify_arg_klass(arg)
27
+ send_self_to_related(arg)
28
+
29
+ instance_variable_set(builder.instance_var_name, arg)
30
+ write_attribute(builder.column_name, arg.nil? ? arg : arg.to_h)
31
+ end
32
+ end
33
+ end
34
+
35
+ def reader
36
+ proc do |builder|
37
+ define_method(builder.field_name) do
38
+ return if read_attribute(builder.column_name).nil?
39
+
40
+ build_related_model if instance_variable_get(builder.instance_var_name).nil?
41
+ instance_variable_get(builder.instance_var_name)
42
+ end
43
+ end
44
+ end
45
+
46
+ def related_model
47
+ proc do |builder|
48
+ private
49
+
50
+ define_method('related_model') do
51
+ builder.related_klass_name.constantize.new(read_attribute(builder.column_name))
52
+ end
53
+ end
54
+ end
55
+
56
+ def build_related_model
57
+ proc do |builder|
58
+ private
59
+
60
+ define_method('build_related_model') do
61
+ instance_variable_set(builder.instance_var_name, related_model)
62
+ related_model.public_send(builder.inverse_set, self) if related_model.respond_to?(builder.inverse_set)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,81 @@
1
+ module Embedson
2
+ module Model
3
+
4
+ class MethodBuilder
5
+
6
+ attr_reader :klass, :field_name, :options
7
+
8
+ def initialize(klass, name, options)
9
+ @klass = klass
10
+ @field_name = name
11
+ @options = options
12
+ end
13
+
14
+ def embeds
15
+ EmbedsBuilder.new(self).define
16
+ generate_common
17
+ end
18
+
19
+ def embedded
20
+ EmbeddedBuilder.new(self).define
21
+ generate_common
22
+ end
23
+
24
+ def column_name
25
+ @column_name ||= options.fetch(:column_name, nil) || field_name
26
+ end
27
+
28
+ def related_klass_name
29
+ @related_klass_name ||= (options.fetch(:class_name, nil) || field_name).to_s.classify
30
+ end
31
+
32
+ def instance_var_name
33
+ @instance_var_name ||= "@#{field_name}"
34
+ end
35
+
36
+ def inverse_get
37
+ @inverse_get ||= options.fetch(:inverse_of, nil) || klass.name.demodulize.tableize.singularize
38
+ end
39
+
40
+ def inverse_set
41
+ @inverse_set ||= "#{inverse_get}="
42
+ end
43
+
44
+ private
45
+
46
+ def generate_common
47
+ methods_for_both.each do |meth|
48
+ klass.class_exec self, &send(meth)
49
+ end
50
+ end
51
+
52
+ def methods_for_both
53
+ [:send_self_to_related, :verify_arg_klass]
54
+ end
55
+
56
+ def verify_arg_klass
57
+ proc do |builder|
58
+ private
59
+
60
+ define_method('verify_arg_klass') do |arg|
61
+ unless arg.nil? || arg.is_a?(builder.related_klass_name.constantize)
62
+ raise ClassTypeError.new(arg.class.name, builder.related_klass_name)
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ def send_self_to_related
69
+ proc do |builder|
70
+ private
71
+
72
+ define_method('send_self_to_related') do |arg|
73
+ if arg.respond_to?(builder.inverse_set) && arg.public_send(builder.inverse_get) != self
74
+ arg.public_send(builder.inverse_set, self)
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -1,3 +1,3 @@
1
1
  module Embedson
2
- VERSION = "0.0.2"
2
+ VERSION = "1.0.1"
3
3
  end
@@ -7,61 +7,60 @@ describe Embedson::Model do
7
7
 
8
8
  with_model :Parent do
9
9
  table do |t|
10
- t.json :embedded
10
+ t.json :embeddeda
11
11
  end
12
12
 
13
13
  model do
14
- extend Embedson::Model
15
-
16
- embeds_one :embedded
14
+ embeds_one :embeddeda
17
15
  end
18
16
  end
19
17
 
20
- class Embedded < OpenStruct
18
+ class Embeddeda
21
19
 
22
20
  def to_h
23
21
  { defined: 'in', embedded: true }
24
22
  end
25
23
  end
26
24
 
27
- let(:parent) { Parent.new() }
28
- let(:embedded) { Embedded.new() }
25
+ let(:parent) { Parent.new }
26
+ let(:embedded) { Embeddeda.new }
29
27
 
30
28
  it 'adds "embeds_one" method' do
31
29
  expect(Parent).to respond_to(:embeds_one)
32
30
  end
33
31
 
34
- it 'adds "embedded" method' do
35
- expect(Parent.new()).to respond_to(:embedded)
32
+ it 'adds "embeddeda" method' do
33
+ expect(parent).to respond_to(:embeddeda)
36
34
  end
37
35
 
38
- it 'adds "embedded=" method' do
39
- expect(Parent.new()).to respond_to("embedded=")
36
+ it 'adds "embeddeda=" method' do
37
+ expect(parent).to respond_to("embeddeda=")
40
38
  end
41
39
 
42
- describe 'defined .embedded= method' do
43
- it 'assigns value of embedded class' do
40
+ describe 'defined .embeddeda= method' do
41
+ it 'assigns value of Embeddeda class' do
42
+
44
43
  expect {
45
- parent.embedded = embedded
46
- }.to change{ parent.embedded }.from(nil).to(embedded)
44
+ parent.embeddeda = embedded
45
+ }.to change{ parent.embeddeda }.from(nil).to(embedded)
47
46
  end
48
47
 
49
48
  context 'when assigning nil' do
50
- let(:parent) { Parent.new(embedded: embedded) }
49
+ let(:parent) { Parent.new(embeddeda: embedded) }
51
50
 
52
51
  it 'removes assignmnent' do
53
52
  parent
54
53
  expect {
55
- parent.embedded = nil
56
- }.to change { parent.embedded }.from(embedded).to(nil)
54
+ parent.embeddeda = nil
55
+ }.to change { parent.embeddeda }.from(embedded).to(nil)
57
56
  end
58
57
  end
59
58
 
60
59
  context 'when assigning wrong class' do
61
- it 'raises TypeError' do
60
+ it 'raises ClassTypeError' do
62
61
  expect{
63
- parent.embedded = 'something'
64
- }.to raise_error(TypeError)
62
+ parent.embeddeda = 'something'
63
+ }.to raise_error(Embedson::ClassTypeError)
65
64
  end
66
65
  end
67
66
 
@@ -72,41 +71,41 @@ describe Embedson::Model do
72
71
 
73
72
  it 'marks parent as changed' do
74
73
  expect {
75
- parent.embedded = embedded
74
+ parent.embeddeda = embedded
76
75
  }.to change{ parent.changed? }.from(false).to(true)
77
76
  end
78
77
 
79
78
  context 'and saved after change' do
80
- it 'saves Embedded class to json column' do
79
+ it 'saves Embeddeda class in column' do
81
80
  expect{
82
- parent.embedded = embedded
81
+ parent.embeddeda = embedded
83
82
  parent.save!
84
- }.to change { parent.reload.read_attribute(:embedded) }.from(nil).to(embedded.to_h.stringify_keys)
83
+ }.to change { parent.reload.read_attribute(:embeddeda) }.from(nil).to(embedded.to_h.stringify_keys)
85
84
  end
86
85
  end
87
86
  end
88
87
  end
89
88
 
90
- describe 'defined embedded method' do
89
+ describe 'defined .embedded method' do
91
90
  context 'when value column is null' do
92
91
  it 'returns nil' do
93
- expect(parent.embedded).to be nil
92
+ expect(parent.embeddeda).to be nil
94
93
  end
95
94
  end
96
95
 
97
- it 'returns embedded class' do
98
- parent.embedded = embedded
99
- expect(parent.embedded).to be_a Embedded
96
+ it 'returns Embeddeda class' do
97
+ parent.embeddeda = embedded
98
+ expect(parent.embeddeda).to be_a Embeddeda
100
99
  end
101
100
 
102
101
  context 'when there is defined value in column' do
103
102
  before do
104
- parent.embedded = embedded
103
+ parent.embeddeda = embedded
105
104
  parent.save!
106
105
  end
107
106
 
108
- it 'returns embedded class initialized with value from column' do
109
- expect(parent.reload.embedded).to eq embedded
107
+ it 'returns Embeddeda class initialized with value from column' do
108
+ expect(parent.reload.embeddeda).to eq embedded
110
109
  end
111
110
  end
112
111
  end
@@ -120,13 +119,11 @@ describe Embedson::Model do
120
119
  end
121
120
 
122
121
  model do
123
- extend Embedson::Model
124
-
125
- embeds_one :embedded, column_name: :data
122
+ embeds_one :embeddedb, column_name: :data
126
123
  end
127
124
  end
128
125
 
129
- class Embedded < OpenStruct
126
+ class Embeddedb < OpenStruct
130
127
 
131
128
  def to_h
132
129
  { defined: 'in', embedded: true }
@@ -134,23 +131,23 @@ describe Embedson::Model do
134
131
  end
135
132
 
136
133
  let(:parent) { Parent.new() }
137
- let(:embedded) { Embedded.new() }
134
+ let(:embedded) { Embeddedb.new() }
138
135
 
139
136
  it 'adds "embeds_one" method' do
140
137
  expect(Parent).to respond_to(:embeds_one)
141
138
  end
142
139
 
143
140
  it 'adds "embedded" method' do
144
- expect(Parent.new()).to respond_to(:embedded)
141
+ expect(parent).to respond_to(:embeddedb)
145
142
  end
146
143
 
147
144
  it 'adds "embedded=" method' do
148
- expect(Parent.new()).to respond_to("embedded=")
145
+ expect(parent).to respond_to("embeddedb=")
149
146
  end
150
147
 
151
148
  it 'saves embedded class to data column' do
152
149
  expect {
153
- parent.embedded = embedded
150
+ parent.embeddedb = embedded
154
151
  parent.save!
155
152
  }.to change{ parent.read_attribute(:data) }.from(nil).to(embedded.to_h.stringify_keys)
156
153
  end
@@ -160,17 +157,15 @@ describe Embedson::Model do
160
157
 
161
158
  with_model :Parent do
162
159
  table do |t|
163
- t.json :embedded
160
+ t.json :embeddedc
164
161
  end
165
162
 
166
163
  model do
167
- extend Embedson::Model
168
-
169
- embeds_one :embedded, inverse_of: :parent_m
164
+ embeds_one :embeddedc, inverse_of: :parent_m
170
165
  end
171
166
  end
172
167
 
173
- class Embedded < OpenStruct
168
+ class Embeddedc < OpenStruct
174
169
  extend Embedson::Model
175
170
 
176
171
  embedded_in :parent_m, class_name: 'Parent'
@@ -180,24 +175,24 @@ describe Embedson::Model do
180
175
  end
181
176
  end
182
177
 
183
- let(:parent) { Parent.new() }
184
- let(:embedded) { Embedded.new() }
178
+ let(:parent) { Parent.new }
179
+ let(:embedded) { Embeddedc.new }
185
180
 
186
181
  it 'adds "embeds_one" method' do
187
182
  expect(Parent).to respond_to(:embeds_one)
188
183
  end
189
184
 
190
185
  it 'adds "embedded" method' do
191
- expect(Parent.new()).to respond_to(:embedded)
186
+ expect(parent).to respond_to(:embeddedc)
192
187
  end
193
188
 
194
189
  it 'adds "embedded=" method' do
195
- expect(Parent.new()).to respond_to("embedded=")
190
+ expect(parent).to respond_to("embeddedc=")
196
191
  end
197
192
 
198
193
  it 'assigns self to parent_m in embedded class' do
199
- parent.embedded = embedded
200
- expect(parent.embedded.parent_m).to eq parent
194
+ parent.embeddedc = embedded
195
+ expect(parent.embeddedc.parent_m).to eq parent
201
196
  end
202
197
  end
203
198
 
@@ -209,13 +204,11 @@ describe Embedson::Model do
209
204
  end
210
205
 
211
206
  model do
212
- extend Embedson::Model
213
-
214
- embeds_one :emb, class_name: 'Embedded', column_name: :embedded
207
+ embeds_one :emb, class_name: 'Embeddedd', column_name: :embedded
215
208
  end
216
209
  end
217
210
 
218
- class Embedded < OpenStruct
211
+ class Embeddedd < OpenStruct
219
212
  extend Embedson::Model
220
213
 
221
214
  embedded_in :parent
@@ -226,23 +219,391 @@ describe Embedson::Model do
226
219
  end
227
220
 
228
221
  let(:parent) { Parent.new(embedded: { some: 'thing' }) }
229
- let(:embedded) { Embedded.new() }
222
+ let(:embedded) { Embeddedd.new() }
230
223
 
231
224
  it 'adds "embeds_one" method' do
232
225
  expect(Parent).to respond_to(:embeds_one)
233
226
  end
234
227
 
235
228
  it 'adds "emb" method' do
236
- expect(Parent.new()).to respond_to(:emb)
229
+ expect(parent).to respond_to(:emb)
237
230
  end
238
231
 
239
232
  it 'adds "emb=" method' do
240
- expect(Parent.new()).to respond_to("emb=")
233
+ expect(parent).to respond_to("emb=")
241
234
  end
242
235
 
243
- it 'assigns self to parent_m in embedded class' do
236
+ it 'returns emb as Embedded' do
237
+ expect(parent.emb).to be_a Embeddedd
244
238
  expect(parent.emb.some).to eq 'thing'
245
239
  end
246
240
  end
247
241
  end
242
+
243
+ describe '#embedded_in' do
244
+ context 'when only relation name is specified' do
245
+
246
+ with_model :Parent do
247
+ table do |t|
248
+ t.json :embeddede
249
+ end
250
+
251
+ model do
252
+ embeds_one :embeddede
253
+ end
254
+ end
255
+
256
+ class Embeddede < OpenStruct
257
+ extend Embedson::Model
258
+
259
+ embedded_in :parent
260
+
261
+ def change=(arg)
262
+ @change = arg
263
+ end
264
+
265
+ def to_h
266
+ h = { defined: 'in', embedded: true }
267
+ h.merge!(change: @change) if @change.present?
268
+ h
269
+ end
270
+ end
271
+
272
+ let(:parent) { Parent.new() }
273
+ let(:embedded) { Embeddede.new() }
274
+
275
+ it 'adds "embeds_one" method' do
276
+ expect(Embeddede).to respond_to(:embedded_in)
277
+ end
278
+
279
+ it 'adds "parent" method' do
280
+ expect(embedded).to respond_to(:parent)
281
+ end
282
+
283
+ it 'adds "parent=" method' do
284
+ expect(embedded).to respond_to("parent=")
285
+ end
286
+
287
+ describe 'defined .parent= method' do
288
+ it 'assigns value of embeding class' do
289
+ expect {
290
+ embedded.parent = parent
291
+ }.to change{ embedded.parent }.from(nil).to(parent)
292
+ end
293
+
294
+ context 'when assigning nil' do
295
+ let(:embedded) { Embeddede.new(parent: parent) }
296
+
297
+ it 'removes assignmnent' do
298
+ parent
299
+ expect {
300
+ embedded.parent = nil
301
+ }.to change { embedded.parent }.from(parent).to(nil)
302
+ end
303
+ end
304
+
305
+ context 'when assigning wrong class' do
306
+ it 'raises ClassTypeError' do
307
+ expect{
308
+ embedded.parent = 'something'
309
+ }.to raise_error(Embedson::ClassTypeError)
310
+ end
311
+ end
312
+
313
+ context 'when parent is persisted' do
314
+ before do
315
+ parent.save!
316
+ end
317
+
318
+ it 'marks parent as changed' do
319
+ expect {
320
+ embedded.parent = parent
321
+ }.to change{ parent.changed? }.from(false).to(true)
322
+ end
323
+
324
+ context 'and saved after change' do
325
+ it 'saves Embedded class in column' do
326
+ expect{
327
+ embedded.parent = parent
328
+ parent.save!
329
+ }.to change { parent.reload.read_attribute(:embeddede) }.from(nil).to(embedded.to_h.stringify_keys)
330
+ end
331
+ end
332
+ end
333
+ end
334
+
335
+ describe 'defined .save method' do
336
+
337
+ context 'when there is parent' do
338
+ let(:embedded) { Embeddede.new(parent: parent) }
339
+
340
+ it 'calls .save on parent' do
341
+ expect(parent).to receive(:save)
342
+ embedded.save
343
+ end
344
+
345
+ it 'saves to_h result in parent column' do
346
+ parent.save!
347
+ expect {
348
+ embedded.save
349
+ }.to change { parent.reload.read_attribute(:embeddede) }.from(nil).to({ "defined" => "in", "embedded" => true })
350
+ end
351
+ end
352
+
353
+ context 'when there is no parent' do
354
+ let(:embedded) { Embeddede.new }
355
+
356
+ it 'returns false' do
357
+ expect(embedded.save).to eq(false)
358
+ end
359
+ end
360
+ end
361
+
362
+ describe 'defined .save! method' do
363
+
364
+ context 'when there is parent' do
365
+ let(:embedded) { Embeddede.new(parent: parent) }
366
+
367
+ it 'calls .save on parent' do
368
+ expect(parent).to receive(:save!)
369
+ embedded.save!
370
+ end
371
+
372
+ it 'saves to_h result in parent column' do
373
+ parent.save!
374
+ expect {
375
+ embedded.save!
376
+ }.to change { parent.reload.read_attribute(:embeddede) }.from(nil).to({ "defined" => "in", "embedded" => true })
377
+ end
378
+ end
379
+
380
+ context 'when there is no parent' do
381
+ it 'raises argument error' do
382
+ expect { embedded.save! }.to raise_error(Embedson::NoParentError)
383
+ end
384
+ end
385
+ end
386
+
387
+ describe 'defined .destroy method' do
388
+
389
+ context 'when there is parent' do
390
+ let(:embedded) { Embeddede.new(parent: parent) }
391
+
392
+ it 'calls .save! on parent' do
393
+ expect(parent).to receive(:save!)
394
+ embedded.destroy
395
+ end
396
+
397
+ it 'saves nil in parent column' do
398
+ embedded.save!
399
+ expect {
400
+ embedded.destroy
401
+ }.to change { parent.reload.read_attribute(:embeddede) }.from({ "defined" => "in", "embedded" => true }).to(nil)
402
+ end
403
+ end
404
+
405
+ context 'when there is no parent' do
406
+ let(:embedded) { Embeddede.new }
407
+
408
+ it 'returns false' do
409
+ expect(embedded.destroy).to eq(false)
410
+ end
411
+ end
412
+ end
413
+
414
+ describe 'defined .embedson_model_changed! method' do
415
+
416
+ context 'when there is parent' do
417
+ let(:embedded) { Embeddede.new(parent: parent) }
418
+
419
+ it 'returns true' do
420
+ expect(embedded.embedson_model_changed!).to eq(true)
421
+ end
422
+
423
+ it 'assigns new value to parent' do
424
+ embedded.change = 'registered'
425
+ expect {
426
+ embedded.embedson_model_changed!
427
+ }.to change { parent.read_attribute(:embeddede) }.from({ "defined" => "in", "embedded" => true }).to({ "defined" => "in", "embedded" => true, 'change' => 'registered' })
428
+ end
429
+ end
430
+
431
+ context 'when there is no parent' do
432
+ it 'raises argument error' do
433
+ expect { embedded.embedson_model_changed! }.to raise_error(Embedson::NoParentError)
434
+ end
435
+ end
436
+ end
437
+
438
+ describe 'defined .initialize method' do
439
+
440
+
441
+ class Embeddedf
442
+ extend Embedson::Model
443
+
444
+ attr_reader :one, :two
445
+
446
+ def initialize(attributes = {})
447
+ @one = attributes[:one]
448
+ @two = attributes[:two]
449
+ end
450
+
451
+ # when you put it before initialize
452
+ # Embeddedf.new(parent: parent)
453
+ # will not owkr
454
+ embedded_in :parent
455
+
456
+ def to_h
457
+ { one: one, two: two }
458
+ end
459
+ end
460
+
461
+ let(:embedded) { Embeddedf.new(one: '1', two: '2', parent: parent)}
462
+
463
+ it 'allows to initialize with parent' do
464
+ expect(embedded.parent).to eq parent
465
+ end
466
+
467
+ it 'keeps initialize working' do
468
+ expect(embedded.to_h).to eq({ one: '1', two: '2' })
469
+ end
470
+ end
471
+ end
472
+
473
+ context 'when options include inverse_of' do
474
+
475
+ with_model :Parent do
476
+ table do |t|
477
+ t.json :emb
478
+ end
479
+
480
+ model do
481
+ embeds_one :emb, class_name: Embeddedg
482
+ end
483
+ end
484
+
485
+ class Embeddedg < OpenStruct
486
+ extend Embedson::Model
487
+
488
+ embedded_in :parent, inverse_of: :emb
489
+
490
+ def to_h
491
+ { defined: 'in', embedded: true }
492
+ end
493
+ end
494
+
495
+ let(:parent) { Parent.new() }
496
+ let(:embedded) { Embeddedg.new() }
497
+
498
+ it 'adds "embeds_one" method' do
499
+ expect(Embeddedg).to respond_to(:embedded_in)
500
+ end
501
+
502
+ it 'adds "parent" method' do
503
+ expect(embedded).to respond_to(:parent)
504
+ end
505
+
506
+ it 'adds "parent=" method' do
507
+ expect(embedded).to respond_to("parent=")
508
+ end
509
+
510
+ it 'assigns self to inverse_of value in parent class' do
511
+ embedded.parent = parent
512
+ expect(embedded.parent.emb).to eq embedded
513
+ end
514
+ end
515
+
516
+ context 'when options include class_name' do
517
+
518
+ with_model :Parented do
519
+ table do |t|
520
+ t.json :embeddedh
521
+ end
522
+
523
+ model do
524
+ embeds_one :embeddedh
525
+ end
526
+ end
527
+
528
+ class Embeddedh < OpenStruct
529
+ extend Embedson::Model
530
+
531
+ embedded_in :parent, class_name: 'Parented'
532
+
533
+ def to_h
534
+ { defined: 'in', embedded: true }
535
+ end
536
+ end
537
+
538
+ let(:parent) { Parented.new }
539
+ let(:embedded) { Embeddedh.new }
540
+
541
+ it 'adds "embeds_one" method' do
542
+ expect(Embeddedh).to respond_to(:embedded_in)
543
+ end
544
+
545
+ it 'adds "parent" method' do
546
+ expect(embedded).to respond_to(:parent)
547
+ end
548
+
549
+ it 'adds "parent=" method' do
550
+ expect(embedded).to respond_to("parent=")
551
+ end
552
+
553
+ describe 'defined .parent method' do
554
+ let(:embedded) { Embeddedh.new(parent: parent) }
555
+
556
+ it 'returns object of Parented class' do
557
+ expect(embedded.parent).to be_a(Parented)
558
+ end
559
+ end
560
+ end
561
+
562
+ context 'when parent model does not have defined embeds_one' do
563
+
564
+ with_model :Parent do
565
+ table do |t|
566
+ t.json :embeddedi
567
+ end
568
+ end
569
+
570
+ class Embeddedi < OpenStruct
571
+ extend Embedson::Model
572
+
573
+ embedded_in :parent
574
+
575
+ def to_h
576
+ { defined: 'in', embedded: true }
577
+ end
578
+ end
579
+
580
+ let(:parent) { Parent.new() }
581
+ let(:embedded) { Embeddedi.new() }
582
+
583
+ it 'adds "embeds_one" method' do
584
+ expect(Embeddedi).to respond_to(:embedded_in)
585
+ end
586
+
587
+ it 'adds "parent" method' do
588
+ expect(embedded).to respond_to(:parent)
589
+ end
590
+
591
+ it 'adds "parent=" method' do
592
+ expect(embedded).to respond_to("parent=")
593
+ end
594
+
595
+ describe 'defined .save method' do
596
+ let(:embedded) { Embeddedi.new(parent: parent) }
597
+
598
+ context 'when there is no to_json method' do
599
+ it 'raises TypeError' do
600
+ parent.save!
601
+ expect {
602
+ embedded.save!
603
+ }.to raise_error(TypeError)
604
+ end
605
+ end
606
+ end
607
+ end
608
+ end
248
609
  end