granite-form 0.1.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -2
  3. data/.github/workflows/{ci.yml → ruby.yml} +22 -4
  4. data/.rubocop.yml +1 -1
  5. data/.rubocop_todo.yml +3 -3
  6. data/Appraisals +1 -2
  7. data/CHANGELOG.md +14 -0
  8. data/README.md +0 -2
  9. data/Rakefile +4 -0
  10. data/docker-compose.yml +14 -0
  11. data/gemfiles/rails.5.0.gemfile +0 -1
  12. data/gemfiles/rails.5.1.gemfile +0 -1
  13. data/gemfiles/rails.5.2.gemfile +0 -1
  14. data/granite-form.gemspec +16 -15
  15. data/lib/granite/form/active_record/associations.rb +1 -1
  16. data/lib/granite/form/base.rb +1 -2
  17. data/lib/granite/form/config.rb +10 -10
  18. data/lib/granite/form/errors.rb +0 -15
  19. data/lib/granite/form/model/associations/base.rb +0 -4
  20. data/lib/granite/form/model/associations/collection/embedded.rb +2 -1
  21. data/lib/granite/form/model/associations/collection/proxy.rb +1 -1
  22. data/lib/granite/form/model/associations/embeds_any.rb +7 -0
  23. data/lib/granite/form/model/associations/embeds_many.rb +9 -58
  24. data/lib/granite/form/model/associations/embeds_one.rb +7 -36
  25. data/lib/granite/form/model/associations/nested_attributes.rb +8 -8
  26. data/lib/granite/form/model/associations/persistence_adapters/active_record.rb +0 -4
  27. data/lib/granite/form/model/associations/persistence_adapters/base.rb +0 -4
  28. data/lib/granite/form/model/associations/references_many.rb +0 -32
  29. data/lib/granite/form/model/associations/references_one.rb +0 -28
  30. data/lib/granite/form/model/associations/reflections/embeds_any.rb +1 -1
  31. data/lib/granite/form/model/associations/reflections/references_any.rb +0 -4
  32. data/lib/granite/form/model/associations/reflections/references_many.rb +3 -1
  33. data/lib/granite/form/model/associations/reflections/references_one.rb +3 -3
  34. data/lib/granite/form/model/associations/reflections/singular.rb +0 -8
  35. data/lib/granite/form/model/associations.rb +0 -6
  36. data/lib/granite/form/model/attributes/attribute.rb +1 -1
  37. data/lib/granite/form/model/attributes/base.rb +14 -17
  38. data/lib/granite/form/model/attributes/collection.rb +1 -1
  39. data/lib/granite/form/model/attributes/dictionary.rb +1 -1
  40. data/lib/granite/form/model/attributes/localized.rb +1 -1
  41. data/lib/granite/form/model/attributes/reference_many.rb +1 -1
  42. data/lib/granite/form/model/attributes/reference_one.rb +1 -9
  43. data/lib/granite/form/model/attributes/reflections/attribute.rb +0 -6
  44. data/lib/granite/form/model/attributes/reflections/base.rb +9 -12
  45. data/lib/granite/form/model/attributes/reflections/reference_one.rb +0 -10
  46. data/lib/granite/form/model/persistence.rb +1 -19
  47. data/lib/granite/form/model/validations/nested.rb +1 -1
  48. data/lib/granite/form/model.rb +0 -2
  49. data/lib/granite/form/types/active_support/time_zone.rb +22 -0
  50. data/lib/granite/form/types/array.rb +17 -0
  51. data/lib/granite/form/types/big_decimal.rb +15 -0
  52. data/lib/granite/form/types/boolean.rb +38 -0
  53. data/lib/granite/form/types/date.rb +15 -0
  54. data/lib/granite/form/types/date_time.rb +15 -0
  55. data/lib/granite/form/types/float.rb +15 -0
  56. data/lib/granite/form/types/hash_with_action_controller_parameters.rb +18 -0
  57. data/lib/granite/form/types/integer.rb +13 -0
  58. data/lib/granite/form/types/object.rb +30 -0
  59. data/lib/granite/form/types/string.rb +13 -0
  60. data/lib/granite/form/types/time.rb +15 -0
  61. data/lib/granite/form/types/uuid.rb +22 -0
  62. data/lib/granite/form/types.rb +15 -0
  63. data/lib/granite/form/version.rb +1 -1
  64. data/lib/granite/form.rb +19 -118
  65. data/spec/{lib/granite → granite}/form/active_record/associations_spec.rb +16 -18
  66. data/spec/{lib/granite → granite}/form/active_record/nested_attributes_spec.rb +0 -1
  67. data/spec/{lib/granite → granite}/form/config_spec.rb +22 -10
  68. data/spec/granite/form/extensions_spec.rb +12 -0
  69. data/spec/{lib/granite → granite}/form/model/associations/embeds_many_spec.rb +29 -305
  70. data/spec/{lib/granite → granite}/form/model/associations/embeds_one_spec.rb +27 -212
  71. data/spec/granite/form/model/associations/nested_attributes_spec.rb +23 -0
  72. data/spec/{lib/granite → granite}/form/model/associations/persistence_adapters/active_record_spec.rb +0 -0
  73. data/spec/granite/form/model/associations/references_many_spec.rb +251 -0
  74. data/spec/granite/form/model/associations/references_one_spec.rb +173 -0
  75. data/spec/{lib/granite → granite}/form/model/associations/reflections/embeds_any_spec.rb +1 -2
  76. data/spec/{lib/granite → granite}/form/model/associations/reflections/embeds_many_spec.rb +18 -26
  77. data/spec/{lib/granite → granite}/form/model/associations/reflections/embeds_one_spec.rb +16 -23
  78. data/spec/{lib/granite → granite}/form/model/associations/reflections/references_many_spec.rb +1 -1
  79. data/spec/{lib/granite → granite}/form/model/associations/reflections/references_one_spec.rb +1 -22
  80. data/spec/{lib/granite → granite}/form/model/associations/validations_spec.rb +0 -3
  81. data/spec/{lib/granite → granite}/form/model/associations_spec.rb +3 -24
  82. data/spec/{lib/granite → granite}/form/model/attributes/attribute_spec.rb +4 -46
  83. data/spec/{lib/granite → granite}/form/model/attributes/base_spec.rb +11 -2
  84. data/spec/{lib/granite → granite}/form/model/attributes/collection_spec.rb +0 -0
  85. data/spec/{lib/granite → granite}/form/model/attributes/dictionary_spec.rb +0 -0
  86. data/spec/{lib/granite → granite}/form/model/attributes/localized_spec.rb +1 -1
  87. data/spec/{lib/granite → granite}/form/model/attributes/reflections/attribute_spec.rb +0 -12
  88. data/spec/{lib/granite → granite}/form/model/attributes/reflections/base_spec.rb +1 -1
  89. data/spec/{lib/granite → granite}/form/model/attributes/reflections/collection_spec.rb +0 -0
  90. data/spec/{lib/granite → granite}/form/model/attributes/reflections/dictionary_spec.rb +0 -0
  91. data/spec/{lib/granite → granite}/form/model/attributes/reflections/localized_spec.rb +0 -0
  92. data/spec/{lib/granite → granite}/form/model/attributes/reflections/represents_spec.rb +0 -0
  93. data/spec/{lib/granite → granite}/form/model/attributes/represents_spec.rb +0 -0
  94. data/spec/{lib/granite → granite}/form/model/attributes_spec.rb +0 -0
  95. data/spec/{lib/granite → granite}/form/model/conventions_spec.rb +0 -0
  96. data/spec/{lib/granite → granite}/form/model/dirty_spec.rb +1 -1
  97. data/spec/{lib/granite → granite}/form/model/persistence_spec.rb +0 -2
  98. data/spec/{lib/granite → granite}/form/model/primary_spec.rb +1 -1
  99. data/spec/{lib/granite → granite}/form/model/representation_spec.rb +0 -0
  100. data/spec/{lib/granite → granite}/form/model/scopes_spec.rb +0 -0
  101. data/spec/{lib/granite → granite}/form/model/validations/associated_spec.rb +2 -4
  102. data/spec/{lib/granite → granite}/form/model/validations/nested_spec.rb +57 -15
  103. data/spec/{lib/granite → granite}/form/model/validations_spec.rb +0 -0
  104. data/spec/{lib/granite → granite}/form/model_spec.rb +0 -0
  105. data/spec/granite/form/types/active_support/time_zone_spec.rb +24 -0
  106. data/spec/granite/form/types/array_spec.rb +13 -0
  107. data/spec/granite/form/types/big_decimal_spec.rb +19 -0
  108. data/spec/granite/form/types/boolean_spec.rb +21 -0
  109. data/spec/granite/form/types/date_spec.rb +18 -0
  110. data/spec/granite/form/types/date_time_spec.rb +20 -0
  111. data/spec/granite/form/types/float_spec.rb +19 -0
  112. data/spec/granite/form/types/hash_with_action_controller_parameters_spec.rb +22 -0
  113. data/spec/granite/form/types/integer_spec.rb +18 -0
  114. data/spec/granite/form/types/object_spec.rb +40 -0
  115. data/spec/granite/form/types/string_spec.rb +13 -0
  116. data/spec/granite/form/types/time_spec.rb +31 -0
  117. data/spec/granite/form/types/uuid_spec.rb +21 -0
  118. data/spec/{lib/granite → granite}/form_spec.rb +0 -0
  119. data/spec/spec_helper.rb +0 -15
  120. data/spec/support/active_record.rb +20 -0
  121. data/spec/{shared → support/shared}/nested_attribute_examples.rb +3 -21
  122. data/spec/support/shared/type_examples.rb +7 -0
  123. metadata +173 -123
  124. data/.github/workflows/main.yml +0 -29
  125. data/gemfiles/rails.4.2.gemfile +0 -15
  126. data/lib/granite/form/model/callbacks.rb +0 -72
  127. data/lib/granite/form/model/lifecycle.rb +0 -309
  128. data/spec/lib/granite/form/model/associations/nested_attributes_spec.rb +0 -119
  129. data/spec/lib/granite/form/model/associations/references_many_spec.rb +0 -572
  130. data/spec/lib/granite/form/model/associations/references_one_spec.rb +0 -445
  131. data/spec/lib/granite/form/model/callbacks_spec.rb +0 -337
  132. data/spec/lib/granite/form/model/lifecycle_spec.rb +0 -356
  133. data/spec/lib/granite/form/model/typecasting_spec.rb +0 -193
@@ -11,12 +11,10 @@ describe Granite::Form::Model::Persistence do
11
11
  end
12
12
 
13
13
  specify { expect(model.new).not_to be_persisted }
14
- specify { expect(model.new).not_to be_destroyed }
15
14
 
16
15
  describe '#instantiate' do
17
16
  specify { expect(model.instantiate({})).to be_an_instance_of model }
18
17
  specify { expect(model.instantiate({})).to be_persisted }
19
- specify { expect(model.instantiate({})).not_to be_destroyed }
20
18
 
21
19
  context do
22
20
  subject(:instance) { model.instantiate(name: 'Hello', foo: 'Bar') }
@@ -54,7 +54,7 @@ describe Granite::Form::Model::Primary do
54
54
  include Granite::Form::Model::Primary
55
55
 
56
56
  primary_attribute type: Integer
57
- attribute :name
57
+ attribute :name, Object
58
58
  end
59
59
  end
60
60
 
@@ -3,8 +3,7 @@ require 'spec_helper'
3
3
  describe Granite::Form::Model::Validations::AssociatedValidator do
4
4
  before do
5
5
  stub_model(:validated_assoc) do
6
- include Granite::Form::Model
7
- include Granite::Form::Model::Lifecycle
6
+ include Granite::Form::Model::Persistence
8
7
 
9
8
  attribute :name, String
10
9
 
@@ -12,8 +11,7 @@ describe Granite::Form::Model::Validations::AssociatedValidator do
12
11
  end
13
12
 
14
13
  stub_model(:unvalidated_assoc) do
15
- include Granite::Form::Model
16
- include Granite::Form::Model::Lifecycle
14
+ include Granite::Form::Model::Persistence
17
15
 
18
16
  attribute :name, String
19
17
  end
@@ -3,8 +3,7 @@ require 'spec_helper'
3
3
  describe Granite::Form::Model::Validations::NestedValidator do
4
4
  before do
5
5
  stub_model(:validated_assoc) do
6
- include Granite::Form::Model
7
- include Granite::Form::Model::Lifecycle
6
+ include Granite::Form::Model::Persistence
8
7
  include Granite::Form::Model::Primary
9
8
 
10
9
  primary :id, Integer
@@ -14,8 +13,7 @@ describe Granite::Form::Model::Validations::NestedValidator do
14
13
  end
15
14
 
16
15
  stub_model(:unvalidated_assoc) do
17
- include Granite::Form::Model
18
- include Granite::Form::Model::Lifecycle
16
+ include Granite::Form::Model::Persistence
19
17
 
20
18
  attribute :name, String
21
19
  end
@@ -114,35 +112,79 @@ describe Granite::Form::Model::Validations::NestedValidator do
114
112
 
115
113
  context 'object field is invalid and referenced object does not include AutosaveAssociation' do
116
114
  before do
117
- stub_class(:validated_object) do
118
- include Granite::Form::Model::Validations
119
- include Granite::Form::Model::Attributes
120
- include Granite::Form::Model::Primary
121
-
122
- primary :id
115
+ stub_model(:validated_object) do
123
116
  attribute :title, String
124
117
  validates_presence_of :title
125
118
  end
126
119
 
127
- Main.class_eval do
128
- include Granite::Form::Model::Associations
120
+ stub_model(:main) do
121
+ include Granite::Form::Model::Persistence
122
+
129
123
  attribute :object, Object
130
124
  validates :object, nested: true
131
125
  end
132
126
  end
133
127
 
134
- subject(:instance) { Main.instantiate name: 'hello', object: object, validated_one: {name: 'name'} }
128
+ subject(:instance) { Main.instantiate name: 'hello', object: object }
135
129
 
136
- context do
130
+ context 'nested object is valid' do
137
131
  let(:object) { ValidatedObject.new(title: 'Mr.') }
132
+
138
133
  it { is_expected.to be_valid }
139
134
  end
140
135
 
141
- context do
136
+ context 'nested object is invalid' do
142
137
  let(:object) { ValidatedObject.new }
138
+
143
139
  it do
144
140
  expect { subject.valid? }.not_to raise_error
145
141
  expect(subject).not_to be_valid
142
+ expect(subject.errors.count).to eq(1)
143
+ end
144
+
145
+ context 'nested validation runs twice' do
146
+ before do
147
+ stub_model(:main) do
148
+ include Granite::Form::Model::Persistence
149
+
150
+ attribute :object, Object
151
+ validates :object, nested: true
152
+ validates :object, nested: true
153
+ end
154
+ end
155
+
156
+ it do
157
+ subject.validate
158
+ expect(subject.errors.count).to eq(1)
159
+ end
160
+
161
+ context 'nested object validation has condition' do
162
+ before do
163
+ stub_model(:validated_object) do
164
+ attribute :title, String
165
+ validates_presence_of :title, if: -> { true }
166
+ end
167
+ end
168
+
169
+ it do
170
+ subject.validate
171
+ expect(subject.errors.count).to eq(1)
172
+ end
173
+ end
174
+
175
+ context 'nested object validation has message' do
176
+ before do
177
+ stub_model(:validated_object) do
178
+ attribute :title, String
179
+ validates_presence_of :title, message: 'test'
180
+ end
181
+ end
182
+
183
+ it do
184
+ subject.validate
185
+ expect(subject.errors.count).to eq(1)
186
+ end
187
+ end
146
188
  end
147
189
  end
148
190
  end
File without changes
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Granite::Form::Types::ActiveSupport::TimeZone do
6
+ describe 'typecasting' do
7
+ include_context 'type setup', 'ActiveSupport::TimeZone'
8
+
9
+ specify { expect(typecast(nil)).to be_nil }
10
+ specify { expect(typecast(Object.new)).to be_nil }
11
+ specify { expect(typecast(Time.now)).to be_nil }
12
+ specify { expect(typecast('blablabla')).to be_nil }
13
+ specify { expect(typecast(TZInfo::Timezone.all.first)).to be_a ActiveSupport::TimeZone }
14
+ specify { expect(typecast('Moscow')).to be_a ActiveSupport::TimeZone }
15
+ specify { expect(typecast('+4')).to be_a ActiveSupport::TimeZone }
16
+ specify { expect(typecast('-3')).to be_a ActiveSupport::TimeZone }
17
+ specify { expect(typecast('3600')).to be_a ActiveSupport::TimeZone }
18
+ specify { expect(typecast('-7200')).to be_a ActiveSupport::TimeZone }
19
+ specify { expect(typecast(4)).to be_a ActiveSupport::TimeZone }
20
+ specify { expect(typecast(-3)).to be_a ActiveSupport::TimeZone }
21
+ specify { expect(typecast(3600)).to be_a ActiveSupport::TimeZone }
22
+ specify { expect(typecast(-7200)).to be_a ActiveSupport::TimeZone }
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Granite::Form::Types::Array do
6
+ describe 'typecasting' do
7
+ include_context 'type setup', 'Array'
8
+
9
+ specify { expect(typecast([1, 2, 3])).to eq([1, 2, 3]) }
10
+ specify { expect(typecast('hello, world')).to eq(%w[hello world]) }
11
+ specify { expect(typecast(10)).to be_nil }
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Granite::Form::Types::BigDecimal do
6
+ describe 'typecasting' do
7
+ include_context 'type setup', 'BigDecimal'
8
+
9
+ specify { expect(typecast('hello')).to be_nil }
10
+ specify { expect(typecast('123hello')).to be_nil }
11
+ specify { expect(typecast('123')).to eq(BigDecimal('123.0')) }
12
+ specify { expect(typecast('123.')).to be_nil }
13
+ specify { expect(typecast('123.5')).to eq(BigDecimal('123.5')) }
14
+ specify { expect(typecast(123)).to eq(BigDecimal('123.0')) }
15
+ specify { expect(typecast(123.5)).to eq(BigDecimal('123.5')) }
16
+ specify { expect(typecast(nil)).to be_nil }
17
+ specify { expect(typecast([123.5])).to be_nil }
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Granite::Form::Types::Boolean do
6
+ describe 'typecasting' do
7
+ include_context 'type setup', 'Boolean'
8
+
9
+ specify { expect(typecast('hello')).to be_nil }
10
+ specify { expect(typecast('true')).to eq(true) }
11
+ specify { expect(typecast('false')).to eq(false) }
12
+ specify { expect(typecast('1')).to eq(true) }
13
+ specify { expect(typecast('0')).to eq(false) }
14
+ specify { expect(typecast(true)).to eq(true) }
15
+ specify { expect(typecast(false)).to eq(false) }
16
+ specify { expect(typecast(1)).to eq(true) }
17
+ specify { expect(typecast(0)).to eq(false) }
18
+ specify { expect(typecast(nil)).to be_nil }
19
+ specify { expect(typecast([123])).to be_nil }
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Granite::Form::Types::Date do
6
+ describe 'typecasting' do
7
+ include_context 'type setup', 'Date'
8
+ let(:date) { Date.new(2013, 6, 13) }
9
+
10
+ specify { expect(typecast(nil)).to be_nil }
11
+ specify { expect(typecast('2013-06-13')).to eq(date) }
12
+ specify { expect(typecast('2013-55-55')).to be_nil }
13
+ specify { expect(typecast('blablabla')).to be_nil }
14
+ specify { expect(typecast(DateTime.new(2013, 6, 13, 23, 13))).to eq(date) } # rubocop:disable Style/DateTime
15
+ specify { expect(typecast(Time.new(2013, 6, 13, 23, 13))).to eq(date) }
16
+ specify { expect(typecast(Date.new(2013, 6, 13))).to eq(date) }
17
+ end
18
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Granite::Form::Types::DateTime do
6
+ # rubocop:disable Style/DateTime
7
+ describe 'typecasting' do
8
+ include_context 'type setup', 'DateTime'
9
+ let(:datetime) { DateTime.new(2013, 6, 13, 23, 13) }
10
+
11
+ specify { expect(typecast(nil)).to be_nil }
12
+ specify { expect(typecast('2013-06-13 23:13')).to eq(datetime) }
13
+ specify { expect(typecast('2013-55-55 55:55')).to be_nil }
14
+ specify { expect(typecast('blablabla')).to be_nil }
15
+ specify { expect(typecast(Date.new(2013, 6, 13))).to eq(DateTime.new(2013, 6, 13, 0, 0)) }
16
+ specify { expect(typecast(Time.utc(2013, 6, 13, 23, 13).utc)).to eq(datetime) }
17
+ specify { expect(typecast(DateTime.new(2013, 6, 13, 23, 13))).to eq(datetime) }
18
+ end
19
+ # rubocop:enable Style/DateTime
20
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Granite::Form::Types::Float do
6
+ describe 'typecasting' do
7
+ include_context 'type setup', 'Float'
8
+
9
+ specify { expect(typecast('hello')).to be_nil }
10
+ specify { expect(typecast('123hello')).to be_nil }
11
+ specify { expect(typecast('123')).to eq(123.0) }
12
+ specify { expect(typecast('123.')).to be_nil }
13
+ specify { expect(typecast('123.5')).to eq(123.5) }
14
+ specify { expect(typecast(123)).to eq(123.0) }
15
+ specify { expect(typecast(123.5)).to eq(123.5) }
16
+ specify { expect(typecast(nil)).to be_nil }
17
+ specify { expect(typecast([123.5])).to be_nil }
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Granite::Form::Types::HashWithActionControllerParameters do
6
+ describe 'typecasting' do
7
+ include_context 'type setup', 'Hash'
8
+
9
+ before(:all) do
10
+ require 'action_controller'
11
+ Class.new(ActionController::Base)
12
+ end
13
+
14
+ let(:to_h) { {'x' => {'foo' => 'bar'}, 'y' => 2} }
15
+ let(:parameters) { ActionController::Parameters.new(to_h) }
16
+
17
+ specify { expect(typecast(nil)).to be_nil }
18
+ specify { expect(typecast(to_h)).to eq(to_h) }
19
+ specify { expect(typecast(parameters)).to be_nil }
20
+ specify { expect(typecast(parameters.permit(:y, x: [:foo]))).to eq(to_h) }
21
+ end
22
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Granite::Form::Types::Integer do
6
+ describe 'typecasting' do
7
+ include_context 'type setup', 'Integer'
8
+
9
+ specify { expect(typecast('hello')).to be_nil }
10
+ specify { expect(typecast('123hello')).to be_nil }
11
+ specify { expect(typecast('123')).to eq(123) }
12
+ specify { expect(typecast('123.5')).to eq(123) }
13
+ specify { expect(typecast(123)).to eq(123) }
14
+ specify { expect(typecast(123.5)).to eq(123) }
15
+ specify { expect(typecast(nil)).to be_nil }
16
+ specify { expect(typecast([123])).to be_nil }
17
+ end
18
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
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) }
9
+
10
+ describe '#initialize' do
11
+ it { is_expected.to have_attributes(type: String, reflection: reflection, owner: an_instance_of(model)) }
12
+ end
13
+
14
+ describe 'typecasting' do
15
+ before { stub_class(:descendant) }
16
+
17
+ context 'with Object type' do
18
+ include_context 'type setup', 'Object'
19
+
20
+ specify { expect(typecast('hello')).to eq('hello') }
21
+ specify { expect(typecast([])).to eq([]) }
22
+ specify { expect(typecast(Descendant.new)).to be_a(Descendant) }
23
+ specify { expect(typecast(Object.new)).to be_a(Object) }
24
+ specify { expect(typecast(nil)).to be_nil }
25
+ end
26
+
27
+ context 'with Descendant type' do
28
+ include_context 'type setup', 'Descendant'
29
+
30
+ before { stub_class(:descendant2, Descendant) }
31
+
32
+ specify { expect(typecast('hello')).to be_nil }
33
+ specify { expect(typecast([])).to be_nil }
34
+ specify { expect(typecast(Descendant.new)).to be_a(Descendant) }
35
+ specify { expect(typecast(Descendant2.new)).to be_a(Descendant2) }
36
+ specify { expect(typecast(Object.new)).to be_nil }
37
+ specify { expect(typecast(nil)).to be_nil }
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Granite::Form::Types::String do
6
+ describe 'typecasting' do
7
+ include_context 'type setup', 'String'
8
+
9
+ specify { expect(typecast('hello')).to eq('hello') }
10
+ specify { expect(typecast(123)).to eq('123') }
11
+ specify { expect(typecast(nil)).to be_nil }
12
+ end
13
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Granite::Form::Types::Time do
6
+ # rubocop:disable Style/DateTime
7
+ describe 'typecasting' do
8
+ include_context 'type setup', 'Time'
9
+
10
+ specify { expect(typecast(nil)).to be_nil }
11
+ specify { expect(typecast('2013-06-13 23:13')).to eq('2013-06-13 23:13'.to_time) }
12
+ specify { expect(typecast('2013-55-55 55:55')).to be_nil }
13
+ specify { expect(typecast('blablabla')).to be_nil }
14
+ specify { expect(typecast(Date.new(2013, 6, 13))).to eq(Time.new(2013, 6, 13, 0, 0)) }
15
+ specify { expect(typecast(DateTime.new(2013, 6, 13, 19, 13))).to eq(DateTime.new(2013, 6, 13, 19, 13).to_time) }
16
+ specify { expect(typecast(Time.new(2013, 6, 13, 23, 13))).to eq(Time.new(2013, 6, 13, 23, 13)) }
17
+
18
+ context 'Time.zone set' do
19
+ around { |example| Time.use_zone('Bangkok', &example) }
20
+
21
+ specify { expect(typecast(nil)).to be_nil }
22
+ specify { expect(typecast('2013-06-13 23:13')).to eq(Time.zone.parse('2013-06-13 23:13')) }
23
+ specify { expect(typecast('2013-55-55 55:55')).to be_nil }
24
+ specify { expect(typecast('blablabla')).to be_nil }
25
+ specify { expect(typecast(Date.new(2013, 6, 13))).to eq(Time.new(2013, 6, 13, 0, 0)) }
26
+ specify { expect(typecast(DateTime.new(2013, 6, 13, 19, 13))).to eq(DateTime.new(2013, 6, 13, 19, 13).to_time) }
27
+ specify { expect(typecast(Time.new(2013, 6, 13, 23, 13))).to eq(Time.new(2013, 6, 13, 23, 13)) }
28
+ end
29
+ end
30
+ # rubocop:enable Style/DateTime
31
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Granite::Form::Types::UUID do
6
+ describe 'typecasting' do
7
+ include_context 'type setup', 'Granite::Form::UUID'
8
+ let(:uuid) { Granite::Form::UUID.random_create }
9
+ let(:uuid_tools) { UUIDTools::UUID.random_create }
10
+
11
+ specify { expect(typecast(nil)).to be_nil }
12
+ specify { expect(typecast(Object.new)).to be_nil }
13
+ specify { expect(typecast(uuid_tools)).to be_a Granite::Form::UUID }
14
+ specify { expect(typecast(uuid_tools)).to eq(uuid_tools) }
15
+ specify { expect(typecast(uuid)).to eq(uuid) }
16
+ specify { expect(typecast(uuid.to_s)).to eq(uuid) }
17
+ specify { expect(typecast(uuid.to_i)).to eq(uuid) }
18
+ specify { expect(typecast(uuid.hexdigest)).to eq(uuid) }
19
+ specify { expect(typecast(uuid.raw)).to eq(uuid) }
20
+ end
21
+ end
File without changes
data/spec/spec_helper.rb CHANGED
@@ -10,21 +10,6 @@ require 'database_cleaner'
10
10
 
11
11
  Dir[File.join(__dir__, 'support', '**', '*.rb')].sort.each { |f| require f }
12
12
 
13
- ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
14
- ActiveRecord::Base.logger = Logger.new('/dev/null')
15
-
16
- ActiveRecord::Schema.define do
17
- create_table :users do |t|
18
- t.column :email, :string
19
- t.column :projects, :text
20
- t.column :profile, :text
21
- end
22
-
23
- create_table :authors do |t|
24
- t.column :name, :string
25
- end
26
- end
27
-
28
13
  RSpec.configure do |config|
29
14
  config.mock_with :rspec
30
15
  config.order = :random
@@ -0,0 +1,20 @@
1
+ ActiveRecord::Base.establish_connection(
2
+ adapter: 'postgresql',
3
+ database: 'granite',
4
+ username: 'granite',
5
+ password: 'granite',
6
+ host: 'localhost'
7
+ )
8
+ ActiveRecord::Base.logger = Logger.new('/dev/null')
9
+
10
+ ActiveRecord::Schema.define do
11
+ create_table :users, force: :cascade do |t|
12
+ t.column :email, :string
13
+ t.column :projects, :text
14
+ t.column :profile, :text
15
+ end
16
+
17
+ create_table :authors, force: :cascade do |t|
18
+ t.column :name, :string
19
+ end
20
+ end
@@ -4,7 +4,7 @@ shared_examples 'nested attributes' do
4
4
  before do
5
5
  stub_model :project do
6
6
  include Granite::Form::Model::Primary
7
- include Granite::Form::Model::Lifecycle
7
+ include Granite::Form::Model::Associations
8
8
 
9
9
  primary :slug, String
10
10
  attribute :title, String
@@ -12,7 +12,7 @@ shared_examples 'nested attributes' do
12
12
 
13
13
  stub_model :profile do
14
14
  include Granite::Form::Model::Primary
15
- include Granite::Form::Model::Lifecycle
15
+ include Granite::Form::Model::Associations
16
16
 
17
17
  primary :identifier
18
18
  attribute :first_name, String
@@ -49,14 +49,12 @@ shared_examples 'nested attributes' do
49
49
  specify do
50
50
  expect do
51
51
  user.profile_attributes = {first_name: 'User 1', _destroy: '1'}
52
- user.save { true }
53
52
  end.not_to change { user.profile.first_name }
54
53
  end
55
54
  specify { expect { user.profile_attributes = {identifier: profile.identifier.to_s, first_name: 'User 1', _destroy: '1'} }.to change { user.profile.first_name }.to('User 1') }
56
55
  specify do
57
56
  expect do
58
57
  user.profile_attributes = {identifier: profile.identifier.to_s, first_name: 'User 1', _destroy: '1'}
59
- user.save { true }
60
58
  end.to change { user.profile.first_name }.to('User 1')
61
59
  end
62
60
 
@@ -67,14 +65,12 @@ shared_examples 'nested attributes' do
67
65
  specify do
68
66
  expect do
69
67
  user.profile_attributes = {first_name: 'User 1', _destroy: '1'}
70
- user.save { true }
71
68
  end.not_to change { user.profile.first_name }
72
69
  end
73
- specify { expect { user.profile_attributes = {identifier: profile.identifier.to_s, first_name: 'User 1', _destroy: '1'} }.to change { user.profile.first_name }.to('User 1') }
70
+ specify { expect { user.profile_attributes = {identifier: profile.identifier.to_s, first_name: 'User 1', _destroy: '1'} }.to change { user.profile }.to(nil) }
74
71
  specify do
75
72
  expect do
76
73
  user.profile_attributes = {identifier: profile.identifier.to_s, first_name: 'User 1', _destroy: '1'}
77
- user.save { true }
78
74
  end.to change { user.profile }.to(nil)
79
75
  end
80
76
  end
@@ -92,8 +88,6 @@ shared_examples 'nested attributes' do
92
88
  context 'not primary' do
93
89
  before do
94
90
  stub_model :profile do
95
- include Granite::Form::Model::Lifecycle
96
-
97
91
  attribute :identifier, Integer
98
92
  attribute :first_name, String
99
93
  end
@@ -245,7 +239,6 @@ shared_examples 'nested attributes' do
245
239
  {slug: projects.first.slug.to_i, title: 'Project 3', _destroy: '1'},
246
240
  {title: 'Project 4', _destroy: '1'}
247
241
  ]
248
- user.save { true }
249
242
  end
250
243
  .to change { user.projects.map(&:title) }.to(['Project 3', 'Project 2'])
251
244
  end
@@ -259,16 +252,6 @@ shared_examples 'nested attributes' do
259
252
  {slug: projects.first.slug.to_i, title: 'Project 3', _destroy: '1'},
260
253
  {title: 'Project 4', _destroy: '1'}
261
254
  ]
262
- end
263
- .to change { user.projects.map(&:title) }.to(['Project 3', 'Project 2'])
264
- end
265
- specify do
266
- expect do
267
- user.projects_attributes = [
268
- {slug: projects.first.slug.to_i, title: 'Project 3', _destroy: '1'},
269
- {title: 'Project 4', _destroy: '1'}
270
- ]
271
- user.save { true }
272
255
  end
273
256
  .to change { user.projects.map(&:title) }.to(['Project 2'])
274
257
  end
@@ -303,7 +286,6 @@ shared_examples 'nested attributes' do
303
286
  before do
304
287
  stub_model :project do
305
288
  include Granite::Form::Model::Primary
306
- include Granite::Form::Model::Lifecycle
307
289
 
308
290
  attribute :slug, String
309
291
  attribute :title, String
@@ -0,0 +1,7 @@
1
+ shared_context 'type setup' do |type_name|
2
+ let(:model) { stub_model { attribute :column, type_name.constantize } }
3
+
4
+ def typecast(value)
5
+ model.new(column: value).column
6
+ end
7
+ end