granite-form 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +1 -1
  3. data/CHANGELOG.md +7 -0
  4. data/Rakefile +4 -0
  5. data/granite-form.gemspec +1 -0
  6. data/lib/granite/form/config.rb +10 -10
  7. data/lib/granite/form/model/associations/nested_attributes.rb +3 -3
  8. data/lib/granite/form/model/associations/reflections/references_many.rb +3 -1
  9. data/lib/granite/form/model/associations/reflections/references_one.rb +3 -1
  10. data/lib/granite/form/model/attributes/attribute.rb +1 -1
  11. data/lib/granite/form/model/attributes/base.rb +13 -16
  12. data/lib/granite/form/model/attributes/collection.rb +1 -1
  13. data/lib/granite/form/model/attributes/dictionary.rb +1 -1
  14. data/lib/granite/form/model/attributes/localized.rb +1 -1
  15. data/lib/granite/form/model/attributes/reference_many.rb +1 -1
  16. data/lib/granite/form/model/attributes/reference_one.rb +1 -9
  17. data/lib/granite/form/model/attributes/reflections/base.rb +1 -5
  18. data/lib/granite/form/model/attributes/reflections/reference_one.rb +0 -4
  19. data/lib/granite/form/model/validations/nested.rb +1 -1
  20. data/lib/granite/form/types/active_support/time_zone.rb +22 -0
  21. data/lib/granite/form/types/array.rb +17 -0
  22. data/lib/granite/form/types/big_decimal.rb +15 -0
  23. data/lib/granite/form/types/boolean.rb +38 -0
  24. data/lib/granite/form/types/date.rb +15 -0
  25. data/lib/granite/form/types/date_time.rb +15 -0
  26. data/lib/granite/form/types/float.rb +15 -0
  27. data/lib/granite/form/types/hash_with_action_controller_parameters.rb +18 -0
  28. data/lib/granite/form/types/integer.rb +13 -0
  29. data/lib/granite/form/types/object.rb +30 -0
  30. data/lib/granite/form/types/string.rb +13 -0
  31. data/lib/granite/form/types/time.rb +15 -0
  32. data/lib/granite/form/types/uuid.rb +22 -0
  33. data/lib/granite/form/types.rb +15 -0
  34. data/lib/granite/form/version.rb +1 -1
  35. data/lib/granite/form.rb +19 -118
  36. data/spec/{lib/granite → granite}/form/active_record/associations_spec.rb +0 -0
  37. data/spec/{lib/granite → granite}/form/active_record/nested_attributes_spec.rb +0 -1
  38. data/spec/{lib/granite → granite}/form/config_spec.rb +22 -10
  39. data/spec/granite/form/extensions_spec.rb +12 -0
  40. data/spec/{lib/granite → granite}/form/model/associations/embeds_many_spec.rb +0 -0
  41. data/spec/{lib/granite → granite}/form/model/associations/embeds_one_spec.rb +0 -0
  42. data/spec/{lib/granite → granite}/form/model/associations/nested_attributes_spec.rb +0 -1
  43. data/spec/{lib/granite → granite}/form/model/associations/persistence_adapters/active_record_spec.rb +0 -0
  44. data/spec/{lib/granite → granite}/form/model/associations/references_many_spec.rb +0 -0
  45. data/spec/{lib/granite → granite}/form/model/associations/references_one_spec.rb +0 -0
  46. data/spec/{lib/granite → granite}/form/model/associations/reflections/embeds_any_spec.rb +0 -0
  47. data/spec/{lib/granite → granite}/form/model/associations/reflections/embeds_many_spec.rb +0 -0
  48. data/spec/{lib/granite → granite}/form/model/associations/reflections/embeds_one_spec.rb +0 -0
  49. data/spec/{lib/granite → granite}/form/model/associations/reflections/references_many_spec.rb +0 -0
  50. data/spec/{lib/granite → granite}/form/model/associations/reflections/references_one_spec.rb +0 -0
  51. data/spec/{lib/granite → granite}/form/model/associations/validations_spec.rb +0 -0
  52. data/spec/{lib/granite → granite}/form/model/associations_spec.rb +0 -0
  53. data/spec/{lib/granite → granite}/form/model/attributes/attribute_spec.rb +4 -46
  54. data/spec/{lib/granite → granite}/form/model/attributes/base_spec.rb +11 -2
  55. data/spec/{lib/granite → granite}/form/model/attributes/collection_spec.rb +0 -0
  56. data/spec/{lib/granite → granite}/form/model/attributes/dictionary_spec.rb +0 -0
  57. data/spec/{lib/granite → granite}/form/model/attributes/localized_spec.rb +1 -1
  58. data/spec/{lib/granite → granite}/form/model/attributes/reflections/attribute_spec.rb +0 -12
  59. data/spec/{lib/granite → granite}/form/model/attributes/reflections/base_spec.rb +1 -1
  60. data/spec/{lib/granite → granite}/form/model/attributes/reflections/collection_spec.rb +0 -0
  61. data/spec/{lib/granite → granite}/form/model/attributes/reflections/dictionary_spec.rb +0 -0
  62. data/spec/{lib/granite → granite}/form/model/attributes/reflections/localized_spec.rb +0 -0
  63. data/spec/{lib/granite → granite}/form/model/attributes/reflections/represents_spec.rb +0 -0
  64. data/spec/{lib/granite → granite}/form/model/attributes/represents_spec.rb +0 -0
  65. data/spec/{lib/granite → granite}/form/model/attributes_spec.rb +0 -0
  66. data/spec/{lib/granite → granite}/form/model/callbacks_spec.rb +0 -0
  67. data/spec/{lib/granite → granite}/form/model/conventions_spec.rb +0 -0
  68. data/spec/{lib/granite → granite}/form/model/dirty_spec.rb +0 -0
  69. data/spec/{lib/granite → granite}/form/model/lifecycle_spec.rb +0 -0
  70. data/spec/{lib/granite → granite}/form/model/persistence_spec.rb +0 -0
  71. data/spec/{lib/granite → granite}/form/model/primary_spec.rb +1 -1
  72. data/spec/{lib/granite → granite}/form/model/representation_spec.rb +0 -0
  73. data/spec/{lib/granite → granite}/form/model/scopes_spec.rb +0 -0
  74. data/spec/{lib/granite → granite}/form/model/validations/associated_spec.rb +0 -0
  75. data/spec/{lib/granite → granite}/form/model/validations/nested_spec.rb +55 -11
  76. data/spec/{lib/granite → granite}/form/model/validations_spec.rb +0 -0
  77. data/spec/{lib/granite → granite}/form/model_spec.rb +0 -0
  78. data/spec/granite/form/types/active_support/time_zone_spec.rb +24 -0
  79. data/spec/granite/form/types/array_spec.rb +13 -0
  80. data/spec/granite/form/types/big_decimal_spec.rb +19 -0
  81. data/spec/granite/form/types/boolean_spec.rb +21 -0
  82. data/spec/granite/form/types/date_spec.rb +18 -0
  83. data/spec/granite/form/types/date_time_spec.rb +20 -0
  84. data/spec/granite/form/types/float_spec.rb +19 -0
  85. data/spec/granite/form/types/hash_with_action_controller_parameters_spec.rb +22 -0
  86. data/spec/granite/form/types/integer_spec.rb +18 -0
  87. data/spec/granite/form/types/object_spec.rb +40 -0
  88. data/spec/granite/form/types/string_spec.rb +13 -0
  89. data/spec/granite/form/types/time_spec.rb +31 -0
  90. data/spec/granite/form/types/uuid_spec.rb +21 -0
  91. data/spec/{lib/granite → granite}/form_spec.rb +0 -0
  92. data/spec/{shared → support/shared}/nested_attribute_examples.rb +0 -0
  93. data/spec/support/shared/type_examples.rb +7 -0
  94. metadata +147 -91
  95. data/spec/lib/granite/form/model/typecasting_spec.rb +0 -193
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df27378689a1bdcdc95593c32c65046ecaab452cc3303839979ace6f1a12ef0f
4
- data.tar.gz: 41b0ee8c8b22f1cf992e7b46c91528b4596ad6b362930c5299b6fde58a9bd2b8
3
+ metadata.gz: ebac9979a786e2a3638b1dd7b21648320c779770c10f7fe63707b38a58c0164c
4
+ data.tar.gz: 604dcf0abda92863e1503b0d977a53ca1de7a39823bfc8a4aabab8d9c6a27045
5
5
  SHA512:
6
- metadata.gz: aef5479a5c58afc85c8e68635fbd8382039c69b8235beaeda74d5caf320540c2fd8aac330f70f4c031abfd37d6a214c3acab0086c9c0a1d3843aedd7aab5a1db
7
- data.tar.gz: 5fcc7f498c8685167096ec9d835c6cc80efec7915b17c32aa27f8e912776d2ef25e215ed24c076e7c8e4cb32790eba060d8a7aac827ff1c2cd8d93819b7ae7e2
6
+ metadata.gz: cfc2c624834fe5d0ad4fadb903e6b9a38eed17778cea3c0cf9430437fb095436429c1a0941fd418e143805b064c1a74c0c959fb57493d96fb9602cdca625f36d
7
+ data.tar.gz: 4937e3d02a378edf48daa770799206b3ecdb91ee71ed1025169e6e3bf4a25bc157c01aea9db54dcb70645728eeb0055ca42be7db23258f0b7f2744d8f7415dd9
data/.rubocop_todo.yml CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  # Offense count: 19
10
10
  Metrics/AbcSize:
11
- Max: 54
11
+ Max: 55
12
12
 
13
13
  # Offense count: 2
14
14
  # Configuration parameters: CountComments.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # master
2
2
 
3
+ ## Next
4
+ ## v0.2.0
5
+
6
+ - Replace typecasters with proper type definitions.
7
+ - Instead of `typecaster(type) { |value, _| ... }` you'll have to use `typecaster(type) { |value| ... }`.
8
+ - Consequently you can access type definition in typecaster, e.g. `typecaster('Object') { |value| value if value.class < type }`, here `type` comes from type definition.
9
+
3
10
  ## v0.1.1
4
11
 
5
12
  - Fixed represented error message copying when represented model uses symbols for `message`.
data/Rakefile CHANGED
@@ -1,6 +1,10 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rspec/core/rake_task'
3
+ require 'bump/tasks'
3
4
 
4
5
  RSpec::Core::RakeTask.new(:spec)
5
6
 
6
7
  task default: :spec
8
+
9
+ Bump.tag_by_default = true
10
+ Bump.changelog = true
data/granite-form.gemspec CHANGED
@@ -17,6 +17,7 @@ Gem::Specification.new do |gem|
17
17
  gem.add_development_dependency 'actionpack', '>= 4.0'
18
18
  gem.add_development_dependency 'activerecord', '>= 4.0'
19
19
  gem.add_development_dependency 'appraisal'
20
+ gem.add_development_dependency 'bump'
20
21
  gem.add_development_dependency 'database_cleaner'
21
22
  gem.add_development_dependency 'rake'
22
23
  gem.add_development_dependency 'rspec', '~> 3.7.0'
@@ -4,7 +4,7 @@ module Granite
4
4
  include Singleton
5
5
 
6
6
  attr_accessor :include_root_in_json, :i18n_scope, :logger, :primary_attribute, :base_class, :base_concern,
7
- :_normalizers, :_typecasters
7
+ :_normalizers, :types
8
8
 
9
9
  def self.delegated
10
10
  public_instance_methods - superclass.public_instance_methods - Singleton.public_instance_methods
@@ -16,7 +16,7 @@ module Granite
16
16
  @logger = Logger.new(STDERR)
17
17
  @primary_attribute = :id
18
18
  @_normalizers = {}
19
- @_typecasters = {}
19
+ @types = {}
20
20
  end
21
21
 
22
22
  def normalizer(name, &block)
@@ -27,16 +27,16 @@ module Granite
27
27
  end
28
28
  end
29
29
 
30
- def typecaster(*classes, &block)
31
- classes = classes.flatten
32
- if block
33
- _typecasters[classes.first.to_s.camelize] = block
34
- else
35
- _typecasters[classes.detect do |klass|
36
- _typecasters[klass.to_s.camelize]
37
- end.to_s.camelize] or raise TypecasterMissing, classes
30
+ def typecaster(class_name, &block)
31
+ types[class_name.to_s.camelize] = Class.new(Types::Object) do
32
+ define_method(:typecast, &block)
38
33
  end
39
34
  end
35
+
36
+ def type_for(klass)
37
+ key = klass.ancestors.grep(Class).map(&:to_s).find(&types) or raise TypecasterMissing, klass
38
+ types.fetch(key)
39
+ end
40
40
  end
41
41
  end
42
42
  end
@@ -74,7 +74,7 @@ module Granite
74
74
  primary_attribute_name = primary_name_for(association.reflection.klass)
75
75
  if existing_record
76
76
  primary_attribute = existing_record.attribute(primary_attribute_name)
77
- primary_attribute_value = primary_attribute.typecast(attributes[primary_attribute_name]) if primary_attribute
77
+ primary_attribute_value = primary_attribute.type_definition.ensure_type(attributes[primary_attribute_name]) if primary_attribute
78
78
  end
79
79
 
80
80
  if existing_record && (!primary_attribute || options[:update_only] || existing_record.primary_attribute == primary_attribute_value)
@@ -123,7 +123,7 @@ module Granite
123
123
  else
124
124
  existing_record = association.target.detect do |record|
125
125
  primary_attribute_value = record.attribute(primary_attribute_name)
126
- .typecast(attributes[primary_attribute_name])
126
+ .type_definition.ensure_type(attributes[primary_attribute_name])
127
127
  record.primary_attribute == primary_attribute_value
128
128
  end
129
129
  if existing_record
@@ -162,7 +162,7 @@ module Granite
162
162
  end
163
163
 
164
164
  def self.destroy_flag?(hash)
165
- Granite::Form.typecaster(Boolean).call(hash[DESTROY_ATTRIBUTE])
165
+ Types::Boolean.typecast(hash[DESTROY_ATTRIBUTE])
166
166
  end
167
167
 
168
168
  def self.reject_new_object?(object, association_name, attributes, options)
@@ -12,7 +12,9 @@ module Granite
12
12
 
13
13
  target.add_attribute(
14
14
  Granite::Form::Model::Attributes::Reflections::ReferenceMany,
15
- reflection.reference_key, association: name
15
+ reflection.reference_key,
16
+ type: reflection.persistence_adapter.primary_key_type,
17
+ association: name
16
18
  )
17
19
 
18
20
  reflection
@@ -14,7 +14,9 @@ module Granite
14
14
 
15
15
  target.add_attribute(
16
16
  Granite::Form::Model::Attributes::Reflections::ReferenceOne,
17
- reflection.reference_key, association: name
17
+ reflection.reference_key,
18
+ type: reflection.persistence_adapter.primary_key_type,
19
+ association: name
18
20
  )
19
21
 
20
22
  reflection
@@ -14,7 +14,7 @@ module Granite
14
14
 
15
15
  def read
16
16
  variable_cache(:value) do
17
- normalize(enumerize(typecast(read_before_type_cast)))
17
+ normalize(enumerize(type_definition.ensure_type(read_before_type_cast)))
18
18
  end
19
19
  end
20
20
 
@@ -3,19 +3,16 @@ module Granite
3
3
  module Model
4
4
  module Attributes
5
5
  class Base
6
- attr_reader :name, :owner
7
- delegate :type, :typecaster, :readonly, to: :reflection
6
+ attr_reader :owner, :reflection
7
+ delegate :name, :readonly, to: :reflection
8
+ delegate :type, to: :type_definition
8
9
 
9
- def initialize(name, owner)
10
- @name = name
10
+ def initialize(reflection, owner)
11
+ @reflection = reflection
11
12
  @owner = owner
12
13
  @origin = :default
13
14
  end
14
15
 
15
- def reflection
16
- @owner.class._attributes[name]
17
- end
18
-
19
16
  def write_value(value, origin: :user)
20
17
  reset
21
18
  @origin = origin
@@ -55,18 +52,14 @@ module Granite
55
52
  !(read.respond_to?(:zero?) ? read.zero? : read.blank?)
56
53
  end
57
54
 
58
- def typecast(value)
59
- if value.instance_of?(type)
60
- value
61
- else
62
- typecaster.call(value, self) unless value.nil?
63
- end
64
- end
65
-
66
55
  def readonly?
67
56
  !!(readonly.is_a?(Proc) ? evaluate(&readonly) : readonly)
68
57
  end
69
58
 
59
+ def type_definition
60
+ @type_definition ||= build_type_definition(reflection.type)
61
+ end
62
+
70
63
  def inspect_attribute
71
64
  value = case read
72
65
  when Date, Time, DateTime
@@ -103,6 +96,10 @@ module Granite
103
96
 
104
97
  private
105
98
 
99
+ def build_type_definition(type)
100
+ Granite::Form.type_for(type).new(type, reflection, owner)
101
+ end
102
+
106
103
  def evaluate(*args, &block)
107
104
  if block.arity >= 0 && block.arity <= args.length
108
105
  owner.instance_exec(*args.first(block.arity), &block)
@@ -5,7 +5,7 @@ module Granite
5
5
  class Collection < Attribute
6
6
  def read
7
7
  @value ||= normalize(read_before_type_cast.map do |value|
8
- enumerize(typecast(value))
8
+ enumerize(type_definition.ensure_type(value))
9
9
  end)
10
10
  end
11
11
 
@@ -11,7 +11,7 @@ module Granite
11
11
  hash = hash.stringify_keys.slice(*keys) if keys.present?
12
12
 
13
13
  normalize(Hash[hash.map do |key, value|
14
- [key, enumerize(typecast(value))]
14
+ [key, enumerize(type_definition.ensure_type(value))]
15
15
  end].with_indifferent_access).with_indifferent_access
16
16
  end
17
17
  end
@@ -5,7 +5,7 @@ module Granite
5
5
  class Localized < Attribute
6
6
  def read
7
7
  @value ||= Hash[read_before_type_cast.map do |locale, value|
8
- [locale.to_s, normalize(enumerize(typecast(value)))]
8
+ [locale.to_s, normalize(enumerize(type_definition.ensure_type(value)))]
9
9
  end]
10
10
  end
11
11
 
@@ -5,7 +5,7 @@ module Granite
5
5
  class ReferenceMany < ReferenceOne
6
6
  def type_casted_value
7
7
  variable_cache(:value) do
8
- read_before_type_cast.map { |id| typecast(id) }
8
+ read_before_type_cast.map { |id| type_definition.ensure_type(id) }
9
9
  end
10
10
  end
11
11
 
@@ -24,7 +24,7 @@ module Granite
24
24
 
25
25
  def type_casted_value
26
26
  variable_cache(:value) do
27
- typecast(read_before_type_cast)
27
+ type_definition.ensure_type(read_before_type_cast)
28
28
  end
29
29
  end
30
30
 
@@ -32,14 +32,6 @@ module Granite
32
32
  @value_cache
33
33
  end
34
34
 
35
- def type
36
- @type ||= association.reflection.persistence_adapter.primary_key_type
37
- end
38
-
39
- def typecaster
40
- @typecaster ||= Granite::Form.typecaster(type.ancestors.grep(Class))
41
- end
42
-
43
35
  private
44
36
 
45
37
  def association
@@ -27,7 +27,7 @@ module Granite
27
27
  end
28
28
 
29
29
  def build_attribute(owner, raw_value = Granite::Form::UNDEFINED)
30
- attribute = self.class.attribute_class.new(name, owner)
30
+ attribute = self.class.attribute_class.new(self, owner)
31
31
  attribute.write_value(raw_value, origin: :persistence) unless raw_value == Granite::Form::UNDEFINED
32
32
  attribute
33
33
  end
@@ -43,10 +43,6 @@ module Granite
43
43
  end
44
44
  end
45
45
 
46
- def typecaster
47
- @typecaster ||= Granite::Form.typecaster(type.ancestors.grep(Class))
48
- end
49
-
50
46
  def readonly
51
47
  @readonly ||= options[:readonly]
52
48
  end
@@ -30,10 +30,6 @@ module Granite
30
30
  RUBY
31
31
  end
32
32
 
33
- def type
34
- Object
35
- end
36
-
37
33
  def inspect_reflection
38
34
  "#{name}: (reference)"
39
35
  end
@@ -19,7 +19,7 @@ module Granite
19
19
  def self.import_errors(from, to, prefix)
20
20
  from.each do |error|
21
21
  key = "#{prefix}.#{error.attribute}"
22
- to.import(error, attribute: key) unless to.added?(key, error.type, error.options)
22
+ to.import(error, attribute: key) unless to.messages_for(key).include?(error.message)
23
23
  end
24
24
  end
25
25
  else
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Granite
4
+ module Form
5
+ module Types
6
+ module ActiveSupport
7
+ class TimeZone < Float
8
+ def typecast(value)
9
+ case value
10
+ when ::ActiveSupport::TimeZone
11
+ value
12
+ when ::TZInfo::Timezone
13
+ ::ActiveSupport::TimeZone[value.name]
14
+ when ::String, ::Numeric, ::ActiveSupport::Duration
15
+ ::ActiveSupport::TimeZone[super || value]
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Granite
4
+ module Form
5
+ module Types
6
+ class Array < Object
7
+ def typecast(value)
8
+ if value.is_a?(::String)
9
+ value.split(',').map(&:strip)
10
+ else
11
+ super
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Granite
4
+ module Form
5
+ module Types
6
+ class BigDecimal < Object
7
+ def typecast(value)
8
+ BigDecimal(Float(value).to_s) if value
9
+ rescue ArgumentError, TypeError
10
+ nil
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Granite
4
+ module Form
5
+ module Types
6
+ class Boolean < Object
7
+ MAPPING = {
8
+ 1 => true,
9
+ 0 => false,
10
+ '1' => true,
11
+ '0' => false,
12
+ 't' => true,
13
+ 'f' => false,
14
+ 'T' => true,
15
+ 'F' => false,
16
+ true => true,
17
+ false => false,
18
+ 'true' => true,
19
+ 'false' => false,
20
+ 'TRUE' => true,
21
+ 'FALSE' => false,
22
+ 'y' => true,
23
+ 'n' => false,
24
+ 'yes' => true,
25
+ 'no' => false
26
+ }.freeze
27
+
28
+ def self.typecast(value)
29
+ MAPPING[value]
30
+ end
31
+
32
+ def typecast(value)
33
+ self.class.typecast(value)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Granite
4
+ module Form
5
+ module Types
6
+ class Date < Object
7
+ def typecast(value)
8
+ value.try(:to_date)
9
+ rescue ArgumentError
10
+ nil
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Granite
4
+ module Form
5
+ module Types
6
+ class DateTime < Object
7
+ def typecast(value)
8
+ value.try(:to_datetime)
9
+ rescue ArgumentError
10
+ nil
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Granite
4
+ module Form
5
+ module Types
6
+ class Float < Object
7
+ def typecast(value)
8
+ Float(value)
9
+ rescue ArgumentError, TypeError
10
+ nil
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Granite
4
+ module Form
5
+ module Types
6
+ class HashWithActionControllerParameters < Object
7
+ def typecast(value)
8
+ case value
9
+ when ActionController::Parameters
10
+ value.to_h if value.permitted?
11
+ when ::Hash then
12
+ value
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Granite
4
+ module Form
5
+ module Types
6
+ class Integer < Float
7
+ def typecast(value)
8
+ super.try(:to_i)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Granite
4
+ module Form
5
+ module Types
6
+ class Object
7
+ attr_reader :reflection, :owner, :type
8
+ delegate :name, to: :reflection
9
+
10
+ def initialize(type, reflection, owner)
11
+ @type = type
12
+ @reflection = reflection
13
+ @owner = owner
14
+ end
15
+
16
+ def ensure_type(value)
17
+ if value.instance_of?(type)
18
+ value
19
+ elsif !value.nil?
20
+ typecast(value)
21
+ end
22
+ end
23
+
24
+ def typecast(value)
25
+ value if value.is_a?(type)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Granite
4
+ module Form
5
+ module Types
6
+ class String < Object
7
+ def typecast(value)
8
+ value.to_s
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Granite
4
+ module Form
5
+ module Types
6
+ class Time < Object
7
+ def typecast(value)
8
+ value.is_a?(::String) && ::Time.zone ? ::Time.zone.parse(value) : value.try(:to_time)
9
+ rescue ArgumentError
10
+ nil
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Granite
4
+ module Form
5
+ module Types
6
+ class UUID < Object
7
+ def typecast(value)
8
+ case value
9
+ when UUIDTools::UUID
10
+ Granite::Form::UUID.parse_raw value.raw
11
+ when Granite::Form::UUID
12
+ value
13
+ when ::String
14
+ Granite::Form::UUID.parse_string value
15
+ when ::Integer
16
+ Granite::Form::UUID.parse_int value
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'granite/form/types/object'
4
+ require 'granite/form/types/array'
5
+ require 'granite/form/types/big_decimal'
6
+ require 'granite/form/types/boolean'
7
+ require 'granite/form/types/date'
8
+ require 'granite/form/types/date_time'
9
+ require 'granite/form/types/hash_with_action_controller_parameters'
10
+ require 'granite/form/types/float'
11
+ require 'granite/form/types/integer'
12
+ require 'granite/form/types/string'
13
+ require 'granite/form/types/time'
14
+ require 'granite/form/types/uuid'
15
+ require 'granite/form/types/active_support/time_zone'
@@ -1,5 +1,5 @@
1
1
  module Granite
2
2
  module Form
3
- VERSION = '0.1.1'.freeze
3
+ VERSION = '0.2.0'.freeze
4
4
  end
5
5
  end