granite-form 0.3.0 → 0.4.0

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 (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
@@ -5,7 +5,6 @@ require 'granite/form/model/scopes'
5
5
  require 'granite/form/model/primary'
6
6
  require 'granite/form/model/persistence'
7
7
  require 'granite/form/model/associations'
8
- require 'granite/form/model/localization'
9
8
  require 'granite/form/model/representation'
10
9
  require 'granite/form/model/dirty'
11
10
 
@@ -22,6 +21,7 @@ module Granite
22
21
  include ActiveModel::Serialization
23
22
  include ActiveModel::Serializers::JSON
24
23
 
24
+ include Util
25
25
  include Conventions
26
26
  include Attributes
27
27
  include Validations
@@ -5,6 +5,8 @@ module Granite
5
5
  module Types
6
6
  module ActiveSupport
7
7
  class TimeZone < Float
8
+ private
9
+
8
10
  def typecast(value)
9
11
  case value
10
12
  when ::ActiveSupport::TimeZone
@@ -4,6 +4,8 @@ module Granite
4
4
  module Form
5
5
  module Types
6
6
  class Array < Object
7
+ private
8
+
7
9
  def typecast(value)
8
10
  if value.is_a?(::String)
9
11
  value.split(',').map(&:strip)
@@ -4,6 +4,8 @@ module Granite
4
4
  module Form
5
5
  module Types
6
6
  class BigDecimal < Object
7
+ private
8
+
7
9
  def typecast(value)
8
10
  BigDecimal(Float(value).to_s) if value
9
11
  rescue ArgumentError, TypeError
@@ -29,6 +29,8 @@ module Granite
29
29
  MAPPING[value]
30
30
  end
31
31
 
32
+ private
33
+
32
34
  def typecast(value)
33
35
  self.class.typecast(value)
34
36
  end
@@ -0,0 +1,11 @@
1
+ module Granite
2
+ module Form
3
+ module Types
4
+ class Collection < HasSubtype
5
+ def prepare(value)
6
+ ::Array.wrap(value).map { |v| subtype_definition.prepare(v) }
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -4,6 +4,8 @@ module Granite
4
4
  module Form
5
5
  module Types
6
6
  class Date < Object
7
+ private
8
+
7
9
  def typecast(value)
8
10
  value.try(:to_date)
9
11
  rescue ArgumentError
@@ -4,6 +4,8 @@ module Granite
4
4
  module Form
5
5
  module Types
6
6
  class DateTime < Object
7
+ private
8
+
7
9
  def typecast(value)
8
10
  value.try(:to_datetime)
9
11
  rescue ArgumentError
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Granite
4
+ module Form
5
+ module Types
6
+ class Dictionary < HasSubtype
7
+ def prepare(value)
8
+ value = to_hash(value)
9
+ value = value.stringify_keys.slice(*reflection.keys) if reflection.keys.present?
10
+ value.transform_values { |v| subtype_definition.prepare(v) }.with_indifferent_access
11
+ end
12
+
13
+ private
14
+
15
+ def to_hash(value)
16
+ Hash[value]
17
+ rescue ArgumentError
18
+ {}
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -4,6 +4,8 @@ module Granite
4
4
  module Form
5
5
  module Types
6
6
  class Float < Object
7
+ private
8
+
7
9
  def typecast(value)
8
10
  Float(value)
9
11
  rescue ArgumentError, TypeError
@@ -0,0 +1,18 @@
1
+ module Granite
2
+ module Form
3
+ module Types
4
+ class HasSubtype
5
+ attr_reader :subtype_definition
6
+ delegate :reflection, :owner, :type, :name, :enum, to: :subtype_definition
7
+
8
+ def initialize(subtype_definition)
9
+ @subtype_definition = subtype_definition
10
+ end
11
+
12
+ def build_duplicate(*args)
13
+ self.class.new(subtype_definition.build_duplicate(*args))
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -4,6 +4,8 @@ module Granite
4
4
  module Form
5
5
  module Types
6
6
  class HashWithActionControllerParameters < Object
7
+ private
8
+
7
9
  def typecast(value)
8
10
  case value
9
11
  when ActionController::Parameters
@@ -4,6 +4,8 @@ module Granite
4
4
  module Form
5
5
  module Types
6
6
  class Integer < Float
7
+ private
8
+
7
9
  def typecast(value)
8
10
  super.try(:to_i)
9
11
  end
@@ -13,6 +13,29 @@ module Granite
13
13
  @owner = owner
14
14
  end
15
15
 
16
+ def build_duplicate(reflection, owner)
17
+ self.class.new(type, reflection, owner)
18
+ end
19
+
20
+ def prepare(value)
21
+ enumerize(ensure_type(value))
22
+ end
23
+
24
+ def enum
25
+ source = owner.evaluate(reflection.enum)
26
+
27
+ case source
28
+ when ::Range
29
+ source.to_a
30
+ when ::Set
31
+ source
32
+ else
33
+ ::Array.wrap(source)
34
+ end.to_set
35
+ end
36
+
37
+ private
38
+
16
39
  def ensure_type(value)
17
40
  if value.instance_of?(type)
18
41
  value
@@ -24,6 +47,11 @@ module Granite
24
47
  def typecast(value)
25
48
  value if value.is_a?(type)
26
49
  end
50
+
51
+ def enumerize(value)
52
+ set = enum if reflection.enum
53
+ value if !set || (set.none? || set.include?(value))
54
+ end
27
55
  end
28
56
  end
29
57
  end
@@ -4,6 +4,8 @@ module Granite
4
4
  module Form
5
5
  module Types
6
6
  class String < Object
7
+ private
8
+
7
9
  def typecast(value)
8
10
  value.to_s
9
11
  end
@@ -4,6 +4,8 @@ module Granite
4
4
  module Form
5
5
  module Types
6
6
  class Time < Object
7
+ private
8
+
7
9
  def typecast(value)
8
10
  value.is_a?(::String) && ::Time.zone ? ::Time.zone.parse(value) : value.try(:to_time)
9
11
  rescue ArgumentError
@@ -4,6 +4,8 @@ module Granite
4
4
  module Form
5
5
  module Types
6
6
  class UUID < Object
7
+ private
8
+
7
9
  def typecast(value)
8
10
  case value
9
11
  when UUIDTools::UUID
@@ -1,11 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'granite/form/types/has_subtype'
3
4
  require 'granite/form/types/object'
4
5
  require 'granite/form/types/array'
5
6
  require 'granite/form/types/big_decimal'
6
7
  require 'granite/form/types/boolean'
8
+ require 'granite/form/types/collection'
7
9
  require 'granite/form/types/date'
8
10
  require 'granite/form/types/date_time'
11
+ require 'granite/form/types/dictionary'
9
12
  require 'granite/form/types/hash_with_action_controller_parameters'
10
13
  require 'granite/form/types/float'
11
14
  require 'granite/form/types/integer'
@@ -0,0 +1,55 @@
1
+ module Granite
2
+ module Form
3
+ module Util
4
+ extend ActiveSupport::Concern
5
+
6
+ # Evaluates value and returns result based on what was passed:
7
+ # - if Proc was passed, then executes it in context of self
8
+ # - if Symbol was passed, then calls a method with that name and returns result
9
+ # - otherwise just returns the value itself
10
+ # @param value [Object] value to evaluate
11
+ # @return [Object] result of evaluation
12
+ def evaluate(value, *args)
13
+ value.is_a?(Symbol) ? evaluate_symbol(value, *args) : evaluate_if_proc(value, *args)
14
+ end
15
+
16
+ # Evaluates value and returns result based on what was passed:
17
+ # - if Proc was passed, then executes it in context of self
18
+ # - otherwise just returns the value itself
19
+ # @param value [Object] value to evaluate
20
+ # @return [Object] result of evaluation
21
+ def evaluate_if_proc(value, *args)
22
+ value.is_a?(Proc) ? evaluate_proc(value, *args) : value
23
+ end
24
+
25
+ # Evaluates `if` or `unless` conditions present in the supplied
26
+ # `options` being it a symbol or callable.
27
+ #
28
+ # @param [Hash] options The method options to evaluate.
29
+ # @option options :if method name or callable
30
+ # @option options :unless method name or callable
31
+ # @return [Boolean] whether conditions are satisfied
32
+ def conditions_satisfied?(**options)
33
+ raise ArgumentError, 'You cannot specify both if and unless' if options.key?(:if) && options.key?(:unless)
34
+
35
+ if options.key?(:if)
36
+ evaluate(options[:if])
37
+ elsif options.key?(:unless)
38
+ !evaluate(options[:unless])
39
+ else
40
+ true
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def evaluate_proc(value, *args)
47
+ instance_exec(*args, &value)
48
+ end
49
+
50
+ def evaluate_symbol(value, *args)
51
+ __send__(value, *args)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,5 +1,5 @@
1
1
  module Granite
2
2
  module Form
3
- VERSION = '0.3.0'.freeze
3
+ VERSION = '0.4.0'.freeze
4
4
  end
5
5
  end
data/lib/granite/form.rb CHANGED
@@ -8,6 +8,7 @@ require 'singleton'
8
8
  require 'active_model'
9
9
 
10
10
  require 'granite/form/version'
11
+ require 'granite/form/util'
11
12
  require 'granite/form/errors'
12
13
  require 'granite/form/extensions'
13
14
  require 'granite/form/undefined_class'
@@ -34,7 +34,7 @@ describe Granite::Form::Model::Associations::ReferencesMany do
34
34
 
35
35
  describe 'book#inspect' do
36
36
  specify { expect(existing_book.inspect).to eq(<<~STR.chomp) }
37
- #<Book authors: #<ReferencesMany [#{author.inspect}]>, title: "Genesis", author_ids: [#{author.id}]>
37
+ #<Book authors: #<ReferencesMany #{[author].inspect.truncate(50, omission: '...]')}>, title: "Genesis", author_ids: [#{author.id}]>
38
38
  STR
39
39
  end
40
40
 
@@ -30,7 +30,7 @@ describe Granite::Form::Model::Associations::ReferencesOne do
30
30
 
31
31
  describe 'book#inspect' do
32
32
  specify { expect(existing_book.inspect).to eq(<<~STR.chomp) }
33
- #<Book author: #<ReferencesOne #{author.inspect}>, title: "My Life", author_id: #{author.id}>
33
+ #<Book author: #<ReferencesOne #{author.inspect.truncate(50)}>, title: "My Life", author_id: #{author.id}>
34
34
  STR
35
35
  end
36
36
 
@@ -127,7 +127,7 @@ describe Granite::Form::Model::Associations::ReferencesOne do
127
127
  end
128
128
  specify do
129
129
  expect { association.writer(new_author) }
130
- .to change { association.reader.try(:attributes) }.from(nil).to('id' => new_author.id, 'name' => 'Morty')
130
+ .to change { association.reader }.from(nil).to(new_author)
131
131
  end
132
132
  specify do
133
133
  expect { association.writer(new_author) }
@@ -160,8 +160,8 @@ describe Granite::Form::Model::Associations::ReferencesOne do
160
160
  end
161
161
  specify do
162
162
  expect { existing_association.writer(new_author) }
163
- .to change { existing_association.reader.try(:attributes) }
164
- .from('id' => author.id, 'name' => 'Johny').to('id' => new_author.id, 'name' => 'Morty')
163
+ .to change { existing_association.reader }
164
+ .from(author).to(new_author)
165
165
  end
166
166
  specify do
167
167
  expect { existing_association.writer(new_author) }
@@ -46,8 +46,6 @@ describe Granite::Form::Model::Attributes::Attribute do
46
46
  specify { expect(attribute.default).to eq(nil) }
47
47
  specify { expect(attribute(default: 'hello').default).to eq('hello') }
48
48
  specify { expect(attribute(default: -> { value }).default).to eq(42) }
49
- specify { expect(attribute(default: ->(object) { object.value }).default).to eq(42) }
50
- specify { expect(attribute(default: ->(*args) { args.first.value }).default).to eq(42) }
51
49
  end
52
50
 
53
51
  describe '#defaultize' do
@@ -57,31 +55,6 @@ describe Granite::Form::Model::Attributes::Attribute do
57
55
  specify { expect(attribute(default: false, type: Boolean).defaultize(nil)).to eq(false) }
58
56
  end
59
57
 
60
- describe '#enum' do
61
- before { allow_any_instance_of(Dummy).to receive_messages(value: 1..5) }
62
-
63
- specify { expect(attribute.enum).to eq([].to_set) }
64
- specify { expect(attribute(enum: []).enum).to eq([].to_set) }
65
- specify { expect(attribute(enum: 'hello').enum).to eq(['hello'].to_set) }
66
- specify { expect(attribute(enum: %w[hello world]).enum).to eq(%w[hello world].to_set) }
67
- specify { expect(attribute(enum: [1..5]).enum).to eq([1..5].to_set) }
68
- specify { expect(attribute(enum: 1..5).enum).to eq((1..5).to_a.to_set) }
69
- specify { expect(attribute(enum: -> { 1..5 }).enum).to eq((1..5).to_a.to_set) }
70
- specify { expect(attribute(enum: -> { 'hello' }).enum).to eq(['hello'].to_set) }
71
- specify { expect(attribute(enum: -> { ['hello', 42] }).enum).to eq(['hello', 42].to_set) }
72
- specify { expect(attribute(enum: -> { value }).enum).to eq((1..5).to_a.to_set) }
73
- specify { expect(attribute(enum: ->(object) { object.value }).enum).to eq((1..5).to_a.to_set) }
74
- end
75
-
76
- describe '#enumerize' do
77
- specify { expect(attribute.enumerize('anything')).to eq('anything') }
78
- specify { expect(attribute(enum: ['hello', 42]).enumerize('hello')).to eq('hello') }
79
- specify { expect(attribute(enum: ['hello', 42]).enumerize('world')).to eq(nil) }
80
- specify { expect(attribute(enum: -> { 'hello' }).enumerize('hello')).to eq('hello') }
81
- specify { expect(attribute(enum: -> { 1..5 }).enumerize(2)).to eq(2) }
82
- specify { expect(attribute(enum: -> { 1..5 }).enumerize(42)).to eq(nil) }
83
- end
84
-
85
58
  describe '#normalize' do
86
59
  specify { expect(attribute.normalize(' hello ')).to eq(' hello ') }
87
60
  specify { expect(attribute(normalizer: ->(v) { v.strip }).normalize(' hello ')).to eq('hello') }
@@ -93,8 +66,6 @@ describe Granite::Form::Model::Attributes::Attribute do
93
66
  let(:other) { 'other' }
94
67
 
95
68
  specify { expect(attribute(normalizer: ->(_v) { value }).normalize(' hello ')).to eq('value') }
96
- specify { expect(attribute(normalizer: ->(_v, object) { object.value }).normalize(' hello ')).to eq('value') }
97
- specify { expect(attribute(normalizer: ->(_v, _object) { other }).normalize(' hello ')).to eq('other') }
98
69
  end
99
70
 
100
71
  context 'integration' do
@@ -43,15 +43,6 @@ describe Granite::Form::Model::Attributes::Reflections::Attribute do
43
43
  specify { expect(reflection(default: -> {}).defaultizer).to be_a Proc }
44
44
  end
45
45
 
46
- describe '#enumerizer' do
47
- specify { expect(reflection.enumerizer).to be_nil }
48
- specify { expect(reflection(enum: 42).enumerizer).to eq(42) }
49
- specify { expect(reflection(enum: -> {}).enumerizer).to be_a Proc }
50
- specify { expect(reflection(in: 42).enumerizer).to eq(42) }
51
- specify { expect(reflection(in: -> {}).enumerizer).to be_a Proc }
52
- specify { expect(reflection(enum: 42, in: -> {}).enumerizer).to eq(42) }
53
- end
54
-
55
46
  describe '#normalizers' do
56
47
  specify { expect(reflection.normalizers).to eq([]) }
57
48
  specify { expect(reflection(normalizer: -> {}).normalizers).to be_a Array }
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Granite::Form::Model::Attributes::Reflections::Base::BuildTypeDefinition do
6
+ def build_type_definition(**options)
7
+ @reflection = Granite::Form::Model::Attributes::Reflections::Base.new(:field, options)
8
+ described_class.new(owner, @reflection).call
9
+ end
10
+
11
+ def have_type(type)
12
+ have_attributes(type: type, reflection: @reflection, owner: owner)
13
+ end
14
+
15
+ before do
16
+ stub_class :owner
17
+ stub_class(:dummy, String)
18
+ end
19
+
20
+ let(:owner) { Owner.new }
21
+
22
+ specify { expect { build_type_definition }.to raise_error('Type is not specified for `field`') }
23
+ specify { expect(build_type_definition(type: String)).to have_type(String) }
24
+ specify { expect(build_type_definition(type: :string)).to have_type(String) }
25
+ specify { expect(build_type_definition(type: Dummy)).to have_type(Dummy) }
26
+ specify { expect { build_type_definition(type: :blabla) }.to raise_error NameError }
27
+ end
@@ -30,6 +30,8 @@ describe Granite::Form::Model::Attributes::Reflections::Base do
30
30
  end
31
31
 
32
32
  describe '#build_attribute' do
33
+ subject { reflection.build_attribute(owner, nil) }
34
+
33
35
  before do
34
36
  stub_class('SomeScope::Borogoves', described_class)
35
37
  stub_class('Granite::Form::Model::Attributes::Borogoves', Granite::Form::Model::Attributes::Base)
@@ -39,18 +41,22 @@ describe Granite::Form::Model::Attributes::Reflections::Base do
39
41
  let(:reflection) { SomeScope::Borogoves.new(:field, type: Object) }
40
42
  let(:owner) { Owner.new }
41
43
 
42
- specify { expect(reflection.build_attribute(owner, nil)).to be_a(Granite::Form::Model::Attributes::Borogoves) }
43
- specify { expect(reflection.build_attribute(owner, nil).name).to eq('field') }
44
- specify { expect(reflection.build_attribute(owner, nil).owner).to eq(owner) }
44
+ it { is_expected.to be_a(Granite::Form::Model::Attributes::Borogoves) }
45
+ it { is_expected.to have_attributes(reflection: reflection, owner: owner, type: Object) }
45
46
  end
46
47
 
47
- describe '#type' do
48
- before { stub_class(:dummy, String) }
48
+ describe '#enum' do
49
+ specify { expect(reflection.enum).to be_nil }
50
+ specify { expect(reflection(enum: 42).enum).to eq(42) }
51
+ specify { expect(reflection(enum: -> {}).enum).to be_a Proc }
52
+ specify { expect(reflection(in: 42).enum).to eq(42) }
53
+ specify { expect(reflection(in: -> {}).enum).to be_a Proc }
54
+ specify { expect(reflection(enum: 42, in: -> {}).enum).to eq(42) }
55
+ end
49
56
 
50
- specify { expect { reflection.type }.to raise_error('Type is not specified for `field`') }
51
- specify { expect(reflection(type: String).type).to eq(String) }
52
- specify { expect(reflection(type: :string).type).to eq(String) }
53
- specify { expect(reflection(type: Dummy).type).to eq(Dummy) }
54
- specify { expect { reflection(type: :blabla).type }.to raise_error NameError }
57
+ describe '#keys' do
58
+ specify { expect(reflection.keys).to eq([]) }
59
+ specify { expect(reflection(keys: ['a', :b]).keys).to eq(%w[a b]) }
60
+ specify { expect(reflection(keys: :c).keys).to eq(%w[c]) }
55
61
  end
56
62
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Granite::Form::Model::Attributes::Reflections::Collection::BuildTypeDefinition do
6
+ def build_type_definition(name = :name, **options)
7
+ @reflection = Granite::Form::Model::Attributes::Reflections::Collection.new(name, options)
8
+ described_class.new(owner, @reflection).call
9
+ end
10
+
11
+ def have_collection_type(type)
12
+ subtype_definition = have_attributes(type: type, reflection: @reflection, owner: owner)
13
+ have_attributes(subtype_definition: subtype_definition)
14
+ end
15
+
16
+ before do
17
+ stub_class :owner
18
+ stub_class(:dummy, String)
19
+ end
20
+
21
+ let(:owner) { Owner.new }
22
+
23
+ it { expect(build_type_definition(type: String)).to have_collection_type(String) }
24
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Granite::Form::Model::Attributes::Reflections::Dictionary::BuildTypeDefinition do
6
+ def build_type_definition(name = :name, **options)
7
+ @reflection = Granite::Form::Model::Attributes::Reflections::Dictionary.new(name, options)
8
+ described_class.new(owner, @reflection).call
9
+ end
10
+
11
+ def have_dictionary_type(type)
12
+ subtype_definition = have_attributes(type: type, reflection: @reflection, owner: owner)
13
+ have_attributes(subtype_definition: subtype_definition)
14
+ end
15
+
16
+ before do
17
+ stub_class :owner
18
+ stub_class(:dummy, String)
19
+ end
20
+
21
+ let(:owner) { Owner.new }
22
+
23
+ it { expect(build_type_definition(type: String)).to have_dictionary_type(String) }
24
+ end
@@ -34,10 +34,4 @@ describe Granite::Form::Model::Attributes::Reflections::Dictionary do
34
34
  expect(Target).to be_method_defined(:field_alias_values)
35
35
  end
36
36
  end
37
-
38
- describe '#keys' do
39
- specify { expect(reflection.keys).to eq([]) }
40
- specify { expect(reflection(keys: ['a', :b]).keys).to eq(%w[a b]) }
41
- specify { expect(reflection(keys: :c).keys).to eq(%w[c]) }
42
- end
43
37
  end