granite-form 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -1
  3. data/CHANGELOG.md +8 -0
  4. data/README.md +6 -13
  5. data/lib/granite/form/model/associations/nested_attributes.rb +2 -2
  6. data/lib/granite/form/model/associations/reflections/embeds_many.rb +1 -1
  7. data/lib/granite/form/model/associations/reflections/embeds_one.rb +11 -1
  8. data/lib/granite/form/model/associations/reflections/references_one.rb +2 -0
  9. data/lib/granite/form/model/associations/reflections/singular.rb +0 -14
  10. data/lib/granite/form/model/attributes/attribute.rb +3 -21
  11. data/lib/granite/form/model/attributes/base.rb +5 -23
  12. data/lib/granite/form/model/attributes/reference_many.rb +1 -1
  13. data/lib/granite/form/model/attributes/reference_one.rb +1 -1
  14. data/lib/granite/form/model/attributes/reflections/attribute.rb +4 -4
  15. data/lib/granite/form/model/attributes/reflections/base/build_type_definition.rb +38 -0
  16. data/lib/granite/form/model/attributes/reflections/base.rb +12 -10
  17. data/lib/granite/form/model/attributes/reflections/collection/build_type_definition.rb +19 -0
  18. data/lib/granite/form/model/attributes/reflections/dictionary/build_type_definition.rb +19 -0
  19. data/lib/granite/form/model/attributes/reflections/dictionary.rb +0 -3
  20. data/lib/granite/form/model/attributes/reflections/represents/build_type_definition.rb +73 -0
  21. data/lib/granite/form/model/attributes/reflections/represents.rb +10 -2
  22. data/lib/granite/form/model/attributes/represents.rb +22 -37
  23. data/lib/granite/form/model/attributes.rb +10 -2
  24. data/lib/granite/form/model/representation.rb +1 -0
  25. data/lib/granite/form/model/validations.rb +6 -0
  26. data/lib/granite/form/model.rb +1 -1
  27. data/lib/granite/form/types/active_support/time_zone.rb +2 -0
  28. data/lib/granite/form/types/array.rb +2 -0
  29. data/lib/granite/form/types/big_decimal.rb +2 -0
  30. data/lib/granite/form/types/boolean.rb +2 -0
  31. data/lib/granite/form/types/collection.rb +11 -0
  32. data/lib/granite/form/types/date.rb +2 -0
  33. data/lib/granite/form/types/date_time.rb +2 -0
  34. data/lib/granite/form/types/dictionary.rb +23 -0
  35. data/lib/granite/form/types/float.rb +2 -0
  36. data/lib/granite/form/types/has_subtype.rb +18 -0
  37. data/lib/granite/form/types/hash_with_action_controller_parameters.rb +2 -0
  38. data/lib/granite/form/types/integer.rb +2 -0
  39. data/lib/granite/form/types/object.rb +28 -0
  40. data/lib/granite/form/types/string.rb +2 -0
  41. data/lib/granite/form/types/time.rb +2 -0
  42. data/lib/granite/form/types/uuid.rb +2 -0
  43. data/lib/granite/form/types.rb +3 -0
  44. data/lib/granite/form/util.rb +55 -0
  45. data/lib/granite/form/version.rb +1 -1
  46. data/lib/granite/form.rb +1 -0
  47. data/spec/granite/form/model/associations/references_many_spec.rb +1 -1
  48. data/spec/granite/form/model/associations/references_one_spec.rb +4 -4
  49. data/spec/granite/form/model/attributes/attribute_spec.rb +0 -29
  50. data/spec/granite/form/model/attributes/reflections/attribute_spec.rb +0 -9
  51. data/spec/granite/form/model/attributes/reflections/base/build_type_definition_spec.rb +27 -0
  52. data/spec/granite/form/model/attributes/reflections/base_spec.rb +16 -10
  53. data/spec/granite/form/model/attributes/reflections/collection/build_type_definition_spec.rb +24 -0
  54. data/spec/granite/form/model/attributes/reflections/dictionary/build_type_definition_spec.rb +24 -0
  55. data/spec/granite/form/model/attributes/reflections/dictionary_spec.rb +0 -6
  56. data/spec/granite/form/model/attributes/reflections/represents/build_type_definition_spec.rb +129 -0
  57. data/spec/granite/form/model/attributes/reflections/represents_spec.rb +43 -20
  58. data/spec/granite/form/model/attributes/represents_spec.rb +78 -55
  59. data/spec/granite/form/model/attributes_spec.rb +84 -23
  60. data/spec/granite/form/model/dirty_spec.rb +0 -6
  61. data/spec/granite/form/model/representation_spec.rb +4 -7
  62. data/spec/granite/form/model/validations_spec.rb +28 -1
  63. data/spec/granite/form/types/collection_spec.rb +22 -0
  64. data/spec/granite/form/types/dictionary_spec.rb +32 -0
  65. data/spec/granite/form/types/has_subtype_spec.rb +20 -0
  66. data/spec/granite/form/types/object_spec.rb +50 -4
  67. data/spec/granite/form/util_spec.rb +108 -0
  68. data/spec/support/active_record.rb +3 -0
  69. metadata +26 -15
  70. data/lib/granite/form/model/attributes/collection.rb +0 -19
  71. data/lib/granite/form/model/attributes/dictionary.rb +0 -28
  72. data/lib/granite/form/model/attributes/localized.rb +0 -44
  73. data/lib/granite/form/model/attributes/reflections/localized.rb +0 -45
  74. data/lib/granite/form/model/localization.rb +0 -26
  75. data/spec/granite/form/model/attributes/collection_spec.rb +0 -72
  76. data/spec/granite/form/model/attributes/dictionary_spec.rb +0 -100
  77. data/spec/granite/form/model/attributes/localized_spec.rb +0 -103
  78. data/spec/granite/form/model/attributes/reflections/localized_spec.rb +0 -37
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Granite::Form::Types::Collection do
4
+ subject(:type) { described_class.new(subtype_definition) }
5
+ let(:element_type) { Dummy }
6
+ let(:subtype_definition) { Granite::Form::Types::Object.new(element_type, reflection, nil) }
7
+ let(:reflection) { Granite::Form::Model::Attributes::Reflections::Base.new(:field) }
8
+ let(:dummy_object) { Dummy.new }
9
+
10
+ before { stub_class :dummy }
11
+
12
+ describe '#prepare' do
13
+ specify { expect(subject.prepare([dummy_object, Object.new])).to eq([dummy_object, nil]) }
14
+ specify { expect(subject.prepare(dummy_object)).to eq([dummy_object]) }
15
+
16
+ context 'with Hash collection' do
17
+ let(:element_type) { Hash }
18
+
19
+ specify { expect(subject.prepare([{key: 'value'}])).to eq([{key: 'value'}]) }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Granite::Form::Types::Dictionary do
6
+ subject(:type) { described_class.new(subtype_definition) }
7
+ let(:element_type) { Dummy }
8
+ let(:subtype_definition) { Granite::Form::Types::Object.new(element_type, reflection, nil) }
9
+ let(:reflection) { build_reflection }
10
+ let(:dummy) { Dummy.new }
11
+ let(:dummy2) { Dummy.new }
12
+
13
+ def build_reflection(**options)
14
+ Granite::Form::Model::Attributes::Reflections::Dictionary.new(:field, options)
15
+ end
16
+
17
+ before { stub_class :dummy }
18
+
19
+ describe '#prepare' do
20
+ specify { expect(subject.prepare(one: dummy, two: Object.new)).to eq('one' => dummy, 'two' => nil) }
21
+ specify { expect(subject.prepare(three: dummy)).to eq('three' => dummy) }
22
+ specify { expect(subject.prepare([['one', dummy]])).to eq('one' => dummy) }
23
+ specify { expect(subject.prepare(nil)).to eq({}) }
24
+
25
+ context 'when keys are set' do
26
+ let(:reflection) { build_reflection keys: %w[one two] }
27
+
28
+ specify { expect(subject.prepare(three: dummy)).to eq({}) }
29
+ specify { expect(subject.prepare(nil)).to eq({}) }
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Granite::Form::Types::HasSubtype do
6
+ subject(:type) { described_class.new(subtype_definition) }
7
+ let(:subtype_definition) { Granite::Form::Types::Object.new(Dummy, reflection, nil) }
8
+ let(:reflection) { Granite::Form::Model::Attributes::Reflections::Base.new(:field) }
9
+ let(:dummy_object) { Dummy.new }
10
+
11
+ before { stub_class :dummy }
12
+
13
+ describe '#build_duplicate' do
14
+ subject { type.build_duplicate(new_reflection, new_model) }
15
+ let(:new_model) { double('new_model') }
16
+ let(:new_reflection) { double('new_reflection') }
17
+
18
+ it { is_expected.to have_attributes(subtype_definition: have_attributes(type: Dummy, reflection: new_reflection, owner: new_model)) }
19
+ end
20
+ end
@@ -3,12 +3,32 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe Granite::Form::Types::Object do
6
- subject(:type) { described_class.new(String, reflection, model.new) }
7
- let(:model) { stub_model }
8
- let(:reflection) { Granite::Form::Model::Attributes::Reflections::Base.new(:field) }
6
+ subject(:type) { build_type(reflection: reflection) }
7
+ let(:model) { Model.new }
8
+ let(:reflection) { build_reflection }
9
+
10
+ before do
11
+ stub_model :model
12
+ end
13
+
14
+ def build_reflection(name: :field, **options)
15
+ Granite::Form::Model::Attributes::Reflections::Base.new(name, options)
16
+ end
17
+
18
+ def build_type(type: String, reflection: nil, **options)
19
+ described_class.new(type, reflection || build_reflection(**options), model)
20
+ end
9
21
 
10
22
  describe '#initialize' do
11
- it { is_expected.to have_attributes(type: String, reflection: reflection, owner: an_instance_of(model)) }
23
+ it { is_expected.to have_attributes(type: String, reflection: reflection, owner: model) }
24
+ end
25
+
26
+ describe '#build_duplicate' do
27
+ subject { type.build_duplicate(new_reflection, new_model) }
28
+ let(:new_model) { double('new_model') }
29
+ let(:new_reflection) { Granite::Form::Model::Attributes::Reflections::Base.new(:new_field) }
30
+
31
+ it { is_expected.to have_attributes(type: String, reflection: new_reflection, owner: new_model) }
12
32
  end
13
33
 
14
34
  describe 'typecasting' do
@@ -37,4 +57,30 @@ RSpec.describe Granite::Form::Types::Object do
37
57
  specify { expect(typecast(nil)).to be_nil }
38
58
  end
39
59
  end
60
+
61
+ describe '#enum' do
62
+ before { allow(model).to receive_messages(value: 1..5) }
63
+
64
+ specify { expect(build_type.enum).to eq([].to_set) }
65
+ specify { expect(build_type(enum: []).enum).to eq([].to_set) }
66
+ specify { expect(build_type(enum: 'hello').enum).to eq(['hello'].to_set) }
67
+ specify { expect(build_type(enum: %w[hello world]).enum).to eq(%w[hello world].to_set) }
68
+ specify { expect(build_type(enum: [1..5]).enum).to eq([1..5].to_set) }
69
+ specify { expect(build_type(enum: 1..5).enum).to eq((1..5).to_a.to_set) }
70
+ specify { expect(build_type(enum: -> { 1..5 }).enum).to eq((1..5).to_a.to_set) }
71
+ specify { expect(build_type(enum: -> { 'hello' }).enum).to eq(['hello'].to_set) }
72
+ specify { expect(build_type(enum: -> { ['hello', 42] }).enum).to eq(['hello', 42].to_set) }
73
+ specify { expect(build_type(enum: -> { value }).enum).to eq((1..5).to_a.to_set) }
74
+ end
75
+
76
+ describe '#prepare' do
77
+ specify { expect(build_type.prepare('anything')).to eq('anything') }
78
+ specify { expect(build_type(enum: %w[hello 42]).prepare('hello')).to eq('hello') }
79
+ specify { expect(build_type(enum: %w[hello 42]).prepare('world')).to eq(nil) }
80
+ specify { expect(build_type(enum: %w[hello 42]).prepare('42')).to eq('42') }
81
+ specify { expect(build_type(enum: %w[hello 42]).prepare(42)).to eq(nil) }
82
+ specify { expect(build_type(enum: -> { 'hello' }).prepare('hello')).to eq('hello') }
83
+ specify { expect(build_type(type: Integer, enum: -> { 1..5 }).prepare(2)).to eq(2) }
84
+ specify { expect(build_type(type: Integer, enum: -> { 1..5 }).prepare(42)).to eq(nil) }
85
+ end
40
86
  end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Granite::Form::Util do
4
+ subject(:dummy) { Dummy.new('John') }
5
+
6
+ before do
7
+ stub_class(:dummy, Object) do
8
+ attr_accessor :name
9
+
10
+ def initialize(name)
11
+ @name = name
12
+ end
13
+
14
+ def full_name(last_name)
15
+ [name, last_name].join(' ')
16
+ end
17
+ end
18
+
19
+ Dummy.include described_class
20
+ end
21
+
22
+ describe '#evaluate' do
23
+ subject { dummy.evaluate(target) }
24
+ let(:target) { 'Peter' }
25
+
26
+ it { is_expected.to eq('Peter') }
27
+
28
+ context 'when symbol is passed' do
29
+ let(:target) { :name }
30
+
31
+ it { is_expected.to eq('John') }
32
+ end
33
+
34
+ context 'when lambda is passed' do
35
+ let(:target) { -> { name } }
36
+
37
+ it { is_expected.to eq('John') }
38
+ end
39
+
40
+ context 'with extra arguments' do
41
+ subject { dummy.evaluate(target, 'Doe') }
42
+
43
+ context 'when symbol is passed' do
44
+ let(:target) { :full_name }
45
+
46
+ it { is_expected.to eq('John Doe') }
47
+ end
48
+
49
+ context 'when lambda is passed' do
50
+ let(:target) { ->(last_name) { ['John', last_name].join(' ') } }
51
+
52
+ it { is_expected.to eq('John Doe') }
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '#evaluate_if_proc' do
58
+ subject { dummy.evaluate(target) }
59
+ let(:target) { 'Peter' }
60
+
61
+ it { is_expected.to eq('Peter') }
62
+
63
+ context 'when lambda is passed' do
64
+ let(:target) { -> { name } }
65
+
66
+ it { is_expected.to eq('John') }
67
+ end
68
+
69
+ context 'with extra arguments' do
70
+ subject { dummy.evaluate(target, 'Doe') }
71
+
72
+ let(:target) { ->(last_name) { ['John', last_name].join(' ') } }
73
+
74
+ it { is_expected.to eq('John Doe') }
75
+ end
76
+ end
77
+
78
+ describe '#conditions_satisfied?' do
79
+ subject { dummy.conditions_satisfied?(**conditions) }
80
+ let(:conditions) { {if: -> { name == 'John' }} }
81
+
82
+ it { is_expected.to be_truthy }
83
+
84
+ context 'when if condition is satisfied' do
85
+ before { dummy.name = 'Peter' }
86
+
87
+ it { is_expected.to be_falsey }
88
+ end
89
+
90
+ context 'when unless condition is passed' do
91
+ let(:conditions) { {unless: :name} }
92
+
93
+ it { is_expected.to be_falsey }
94
+ end
95
+
96
+ context 'when no condition is passed' do
97
+ let(:conditions) { {} }
98
+
99
+ it { is_expected.to be_truthy }
100
+ end
101
+
102
+ context 'when both if & unless are passed' do
103
+ let(:conditions) { {if: :name, unless: :name} }
104
+
105
+ it { expect { subject }.to raise_error(ArgumentError) }
106
+ end
107
+ end
108
+ end
@@ -16,5 +16,8 @@ ActiveRecord::Schema.define do
16
16
 
17
17
  create_table :authors, force: :cascade do |t|
18
18
  t.column :name, :string
19
+ t.column :status, :integer
20
+ t.column :related_ids, :integer, array: true
21
+ t.column :data, :text
19
22
  end
20
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: granite-form
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Toptal Engineering
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-22 00:00:00.000000000 Z
11
+ date: 2023-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -268,23 +268,22 @@ files:
268
268
  - lib/granite/form/model/attributes.rb
269
269
  - lib/granite/form/model/attributes/attribute.rb
270
270
  - lib/granite/form/model/attributes/base.rb
271
- - lib/granite/form/model/attributes/collection.rb
272
- - lib/granite/form/model/attributes/dictionary.rb
273
- - lib/granite/form/model/attributes/localized.rb
274
271
  - lib/granite/form/model/attributes/reference_many.rb
275
272
  - lib/granite/form/model/attributes/reference_one.rb
276
273
  - lib/granite/form/model/attributes/reflections/attribute.rb
277
274
  - lib/granite/form/model/attributes/reflections/base.rb
275
+ - lib/granite/form/model/attributes/reflections/base/build_type_definition.rb
278
276
  - lib/granite/form/model/attributes/reflections/collection.rb
277
+ - lib/granite/form/model/attributes/reflections/collection/build_type_definition.rb
279
278
  - lib/granite/form/model/attributes/reflections/dictionary.rb
280
- - lib/granite/form/model/attributes/reflections/localized.rb
279
+ - lib/granite/form/model/attributes/reflections/dictionary/build_type_definition.rb
281
280
  - lib/granite/form/model/attributes/reflections/reference_many.rb
282
281
  - lib/granite/form/model/attributes/reflections/reference_one.rb
283
282
  - lib/granite/form/model/attributes/reflections/represents.rb
283
+ - lib/granite/form/model/attributes/reflections/represents/build_type_definition.rb
284
284
  - lib/granite/form/model/attributes/represents.rb
285
285
  - lib/granite/form/model/conventions.rb
286
286
  - lib/granite/form/model/dirty.rb
287
- - lib/granite/form/model/localization.rb
288
287
  - lib/granite/form/model/persistence.rb
289
288
  - lib/granite/form/model/primary.rb
290
289
  - lib/granite/form/model/representation.rb
@@ -298,9 +297,12 @@ files:
298
297
  - lib/granite/form/types/array.rb
299
298
  - lib/granite/form/types/big_decimal.rb
300
299
  - lib/granite/form/types/boolean.rb
300
+ - lib/granite/form/types/collection.rb
301
301
  - lib/granite/form/types/date.rb
302
302
  - lib/granite/form/types/date_time.rb
303
+ - lib/granite/form/types/dictionary.rb
303
304
  - lib/granite/form/types/float.rb
305
+ - lib/granite/form/types/has_subtype.rb
304
306
  - lib/granite/form/types/hash_with_action_controller_parameters.rb
305
307
  - lib/granite/form/types/integer.rb
306
308
  - lib/granite/form/types/object.rb
@@ -308,6 +310,7 @@ files:
308
310
  - lib/granite/form/types/time.rb
309
311
  - lib/granite/form/types/uuid.rb
310
312
  - lib/granite/form/undefined_class.rb
313
+ - lib/granite/form/util.rb
311
314
  - lib/granite/form/version.rb
312
315
  - spec/granite/form/active_record/associations_spec.rb
313
316
  - spec/granite/form/active_record/nested_attributes_spec.rb
@@ -328,14 +331,14 @@ files:
328
331
  - spec/granite/form/model/associations_spec.rb
329
332
  - spec/granite/form/model/attributes/attribute_spec.rb
330
333
  - spec/granite/form/model/attributes/base_spec.rb
331
- - spec/granite/form/model/attributes/collection_spec.rb
332
- - spec/granite/form/model/attributes/dictionary_spec.rb
333
- - spec/granite/form/model/attributes/localized_spec.rb
334
334
  - spec/granite/form/model/attributes/reflections/attribute_spec.rb
335
+ - spec/granite/form/model/attributes/reflections/base/build_type_definition_spec.rb
335
336
  - spec/granite/form/model/attributes/reflections/base_spec.rb
337
+ - spec/granite/form/model/attributes/reflections/collection/build_type_definition_spec.rb
336
338
  - spec/granite/form/model/attributes/reflections/collection_spec.rb
339
+ - spec/granite/form/model/attributes/reflections/dictionary/build_type_definition_spec.rb
337
340
  - spec/granite/form/model/attributes/reflections/dictionary_spec.rb
338
- - spec/granite/form/model/attributes/reflections/localized_spec.rb
341
+ - spec/granite/form/model/attributes/reflections/represents/build_type_definition_spec.rb
339
342
  - spec/granite/form/model/attributes/reflections/represents_spec.rb
340
343
  - spec/granite/form/model/attributes/represents_spec.rb
341
344
  - spec/granite/form/model/attributes_spec.rb
@@ -353,15 +356,19 @@ files:
353
356
  - spec/granite/form/types/array_spec.rb
354
357
  - spec/granite/form/types/big_decimal_spec.rb
355
358
  - spec/granite/form/types/boolean_spec.rb
359
+ - spec/granite/form/types/collection_spec.rb
356
360
  - spec/granite/form/types/date_spec.rb
357
361
  - spec/granite/form/types/date_time_spec.rb
362
+ - spec/granite/form/types/dictionary_spec.rb
358
363
  - spec/granite/form/types/float_spec.rb
364
+ - spec/granite/form/types/has_subtype_spec.rb
359
365
  - spec/granite/form/types/hash_with_action_controller_parameters_spec.rb
360
366
  - spec/granite/form/types/integer_spec.rb
361
367
  - spec/granite/form/types/object_spec.rb
362
368
  - spec/granite/form/types/string_spec.rb
363
369
  - spec/granite/form/types/time_spec.rb
364
370
  - spec/granite/form/types/uuid_spec.rb
371
+ - spec/granite/form/util_spec.rb
365
372
  - spec/granite/form_spec.rb
366
373
  - spec/spec_helper.rb
367
374
  - spec/support/active_record.rb
@@ -412,14 +419,14 @@ test_files:
412
419
  - spec/granite/form/model/associations_spec.rb
413
420
  - spec/granite/form/model/attributes/attribute_spec.rb
414
421
  - spec/granite/form/model/attributes/base_spec.rb
415
- - spec/granite/form/model/attributes/collection_spec.rb
416
- - spec/granite/form/model/attributes/dictionary_spec.rb
417
- - spec/granite/form/model/attributes/localized_spec.rb
418
422
  - spec/granite/form/model/attributes/reflections/attribute_spec.rb
423
+ - spec/granite/form/model/attributes/reflections/base/build_type_definition_spec.rb
419
424
  - spec/granite/form/model/attributes/reflections/base_spec.rb
425
+ - spec/granite/form/model/attributes/reflections/collection/build_type_definition_spec.rb
420
426
  - spec/granite/form/model/attributes/reflections/collection_spec.rb
427
+ - spec/granite/form/model/attributes/reflections/dictionary/build_type_definition_spec.rb
421
428
  - spec/granite/form/model/attributes/reflections/dictionary_spec.rb
422
- - spec/granite/form/model/attributes/reflections/localized_spec.rb
429
+ - spec/granite/form/model/attributes/reflections/represents/build_type_definition_spec.rb
423
430
  - spec/granite/form/model/attributes/reflections/represents_spec.rb
424
431
  - spec/granite/form/model/attributes/represents_spec.rb
425
432
  - spec/granite/form/model/attributes_spec.rb
@@ -437,15 +444,19 @@ test_files:
437
444
  - spec/granite/form/types/array_spec.rb
438
445
  - spec/granite/form/types/big_decimal_spec.rb
439
446
  - spec/granite/form/types/boolean_spec.rb
447
+ - spec/granite/form/types/collection_spec.rb
440
448
  - spec/granite/form/types/date_spec.rb
441
449
  - spec/granite/form/types/date_time_spec.rb
450
+ - spec/granite/form/types/dictionary_spec.rb
442
451
  - spec/granite/form/types/float_spec.rb
452
+ - spec/granite/form/types/has_subtype_spec.rb
443
453
  - spec/granite/form/types/hash_with_action_controller_parameters_spec.rb
444
454
  - spec/granite/form/types/integer_spec.rb
445
455
  - spec/granite/form/types/object_spec.rb
446
456
  - spec/granite/form/types/string_spec.rb
447
457
  - spec/granite/form/types/time_spec.rb
448
458
  - spec/granite/form/types/uuid_spec.rb
459
+ - spec/granite/form/util_spec.rb
449
460
  - spec/granite/form_spec.rb
450
461
  - spec/spec_helper.rb
451
462
  - spec/support/active_record.rb
@@ -1,19 +0,0 @@
1
- module Granite
2
- module Form
3
- module Model
4
- module Attributes
5
- class Collection < Attribute
6
- def read
7
- @value ||= normalize(read_before_type_cast.map do |value|
8
- enumerize(type_definition.ensure_type(value))
9
- end)
10
- end
11
-
12
- def read_before_type_cast
13
- @value_before_type_cast ||= Array.wrap(@value_cache).map { |value| defaultize(value) }
14
- end
15
- end
16
- end
17
- end
18
- end
19
- end
@@ -1,28 +0,0 @@
1
- module Granite
2
- module Form
3
- module Model
4
- module Attributes
5
- class Dictionary < Attribute
6
- delegate :keys, to: :reflection
7
-
8
- def read
9
- @value ||= begin
10
- hash = read_before_type_cast
11
- hash = hash.stringify_keys.slice(*keys) if keys.present?
12
-
13
- normalize(Hash[hash.map do |key, value|
14
- [key, enumerize(type_definition.ensure_type(value))]
15
- end].with_indifferent_access).with_indifferent_access
16
- end
17
- end
18
-
19
- def read_before_type_cast
20
- @value_before_type_cast ||= Hash[(@value_cache.presence || {}).map do |key, value|
21
- [key, defaultize(value)]
22
- end].with_indifferent_access
23
- end
24
- end
25
- end
26
- end
27
- end
28
- end
@@ -1,44 +0,0 @@
1
- module Granite
2
- module Form
3
- module Model
4
- module Attributes
5
- class Localized < Attribute
6
- def read
7
- @value ||= Hash[read_before_type_cast.map do |locale, value|
8
- [locale.to_s, normalize(enumerize(type_definition.ensure_type(value)))]
9
- end]
10
- end
11
-
12
- def read_before_type_cast
13
- @value_before_type_cast ||= Hash[(@value_cache.presence || {}).map do |locale, value|
14
- [locale.to_s, defaultize(value)]
15
- end]
16
- end
17
-
18
- def write_locale(value, locale)
19
- pollute do
20
- write(read.merge(locale.to_s => value))
21
- end
22
- end
23
-
24
- def read_locale(locale)
25
- read[owner.class.fallbacks(locale).detect do |fallback|
26
- read[fallback.to_s]
27
- end.to_s]
28
- end
29
-
30
- def read_locale_before_type_cast(locale)
31
- read_before_type_cast[owner.class.fallbacks(locale).detect do |fallback|
32
- read_before_type_cast[fallback.to_s]
33
- end.to_s]
34
- end
35
-
36
- def locale_query(locale)
37
- value = read_locale(locale)
38
- !(value.respond_to?(:zero?) ? value.zero? : value.blank?)
39
- end
40
- end
41
- end
42
- end
43
- end
44
- end
@@ -1,45 +0,0 @@
1
- module Granite
2
- module Form
3
- module Model
4
- module Attributes
5
- module Reflections
6
- class Localized < Attribute
7
- def self.build(target, generated_methods, name, *args, &block)
8
- attribute = super(target, generated_methods, name, *args, &block)
9
- generate_methods name, generated_methods
10
- attribute
11
- end
12
-
13
- def self.generate_methods(name, target)
14
- target.class_eval <<-RUBY, __FILE__, __LINE__ + 1
15
- def #{name}_translations
16
- attribute('#{name}').read
17
- end
18
-
19
- def #{name}_translations= value
20
- attribute('#{name}').write(value)
21
- end
22
-
23
- def #{name}
24
- attribute('#{name}').read_locale(self.class.locale)
25
- end
26
-
27
- def #{name}= value
28
- attribute('#{name}').write_locale(value, self.class.locale)
29
- end
30
-
31
- def #{name}?
32
- attribute('#{name}').locale_query(self.class.locale)
33
- end
34
-
35
- def #{name}_before_type_cast
36
- attribute('#{name}').read_locale_before_type_cast(self.class.locale)
37
- end
38
- RUBY
39
- end
40
- end
41
- end
42
- end
43
- end
44
- end
45
- end
@@ -1,26 +0,0 @@
1
- require 'granite/form/model/attributes/reflections/localized'
2
- require 'granite/form/model/attributes/localized'
3
-
4
- module Granite
5
- module Form
6
- module Model
7
- module Localization
8
- extend ActiveSupport::Concern
9
-
10
- module ClassMethods
11
- def localized(*args, &block)
12
- add_attribute(Granite::Form::Model::Attributes::Reflections::Localized, *args, &block)
13
- end
14
-
15
- def fallbacks(locale)
16
- ::I18n.respond_to?(:fallbacks) ? ::I18n.fallbacks[locale] : [locale]
17
- end
18
-
19
- def locale
20
- I18n.locale
21
- end
22
- end
23
- end
24
- end
25
- end
26
- end
@@ -1,72 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Granite::Form::Model::Attributes::Collection do
4
- before { stub_model(:dummy) }
5
-
6
- def attribute(*args)
7
- options = args.extract_options!
8
- Dummy.add_attribute(Granite::Form::Model::Attributes::Reflections::Collection, :field, options)
9
- Dummy.new.attribute(:field)
10
- end
11
-
12
- describe '#read' do
13
- let(:field) { attribute(type: String, normalizer: ->(v) { v.uniq }, default: :world, enum: %w[hello 42]) }
14
-
15
- specify { expect(field.tap { |r| r.write(nil) }.read).to eq([]) }
16
- specify { expect(field.tap { |r| r.write([nil]) }.read).to eq([nil]) }
17
- specify { expect(field.tap { |r| r.write('hello') }.read).to eq(['hello']) }
18
- specify { expect(field.tap { |r| r.write([42]) }.read).to eq(['42']) }
19
- specify { expect(field.tap { |r| r.write([43]) }.read).to eq([nil]) }
20
- specify { expect(field.tap { |r| r.write([43, 44]) }.read).to eq([nil]) }
21
- specify { expect(field.tap { |r| r.write(['']) }.read).to eq([nil]) }
22
- specify { expect(field.tap { |r| r.write(['hello', 42]) }.read).to eq(%w[hello 42]) }
23
- specify { expect(field.tap { |r| r.write(['hello', false]) }.read).to eq(['hello', nil]) }
24
-
25
- context do
26
- let(:field) { attribute(type: String, normalizer: ->(v) { v.uniq }, default: :world) }
27
-
28
- specify { expect(field.tap { |r| r.write(nil) }.read).to eq([]) }
29
- specify { expect(field.tap { |r| r.write([nil, nil]) }.read).to eq(['world']) }
30
- specify { expect(field.tap { |r| r.write('hello') }.read).to eq(['hello']) }
31
- specify { expect(field.tap { |r| r.write([42]) }.read).to eq(['42']) }
32
- specify { expect(field.tap { |r| r.write(['']) }.read).to eq(['']) }
33
- end
34
- end
35
-
36
- describe '#read_before_type_cast' do
37
- let(:field) { attribute(type: String, default: :world, enum: %w[hello 42]) }
38
-
39
- specify { expect(field.tap { |r| r.write(nil) }.read_before_type_cast).to eq([]) }
40
- specify { expect(field.tap { |r| r.write([nil]) }.read_before_type_cast).to eq([:world]) }
41
- specify { expect(field.tap { |r| r.write('hello') }.read_before_type_cast).to eq(['hello']) }
42
- specify { expect(field.tap { |r| r.write([42]) }.read_before_type_cast).to eq([42]) }
43
- specify { expect(field.tap { |r| r.write([43]) }.read_before_type_cast).to eq([43]) }
44
- specify { expect(field.tap { |r| r.write([43, 44]) }.read_before_type_cast).to eq([43, 44]) }
45
- specify { expect(field.tap { |r| r.write(['']) }.read_before_type_cast).to eq(['']) }
46
- specify { expect(field.tap { |r| r.write(['hello', 42]) }.read_before_type_cast).to eq(['hello', 42]) }
47
- specify { expect(field.tap { |r| r.write(['hello', false]) }.read_before_type_cast).to eq(['hello', false]) }
48
-
49
- context do
50
- let(:field) { attribute(type: String, default: :world) }
51
-
52
- specify { expect(field.tap { |r| r.write(nil) }.read_before_type_cast).to eq([]) }
53
- specify { expect(field.tap { |r| r.write([nil, nil]) }.read_before_type_cast).to eq(%i[world world]) }
54
- specify { expect(field.tap { |r| r.write('hello') }.read_before_type_cast).to eq(['hello']) }
55
- specify { expect(field.tap { |r| r.write([42]) }.read_before_type_cast).to eq([42]) }
56
- specify { expect(field.tap { |r| r.write(['']) }.read_before_type_cast).to eq(['']) }
57
- end
58
- end
59
-
60
- context 'integration' do
61
- before do
62
- stub_model(:post) do
63
- collection :tags, String
64
- end
65
- end
66
-
67
- specify { expect(Post.new(tags: ['hello', 42]).tags).to eq(%w[hello 42]) }
68
- specify { expect(Post.new(tags: ['hello', 42]).tags_before_type_cast).to eq(['hello', 42]) }
69
- specify { expect(Post.new.tags?).to eq(false) }
70
- specify { expect(Post.new(tags: ['hello', 42]).tags?).to eq(true) }
71
- end
72
- end