active_type 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +21 -0
- data/active_type.gemspec +1 -1
- data/gemfiles/Gemfile.3.2.mysql2.lock +1 -1
- data/gemfiles/Gemfile.3.2.sqlite3.lock +1 -1
- data/gemfiles/Gemfile.4.0.sqlite3.lock +1 -1
- data/gemfiles/Gemfile.4.1.sqlite3.lock +1 -1
- data/gemfiles/Gemfile.4.2.1.mysql2.lock +1 -1
- data/gemfiles/Gemfile.4.2.1.pg.lock +1 -1
- data/gemfiles/Gemfile.4.2.1.sqlite3.lock +1 -1
- data/gemfiles/Gemfile.5.0.0.mysql2.lock +1 -1
- data/gemfiles/Gemfile.5.0.0.pg.lock +1 -1
- data/gemfiles/Gemfile.5.0.0.sqlite3.lock +1 -1
- data/lib/active_type/version.rb +1 -1
- metadata +3 -53
- data/spec/active_type/extended_record/single_table_inheritance_spec.rb +0 -62
- data/spec/active_type/extended_record_spec.rb +0 -233
- data/spec/active_type/nested_attributes_spec.rb +0 -704
- data/spec/active_type/object_spec.rb +0 -463
- data/spec/active_type/record_spec.rb +0 -274
- data/spec/active_type/util_spec.rb +0 -142
- data/spec/integration/holidays_spec.rb +0 -102
- data/spec/integration/shape_spec.rb +0 -110
- data/spec/integration/sign_in_spec.rb +0 -101
- data/spec/integration/sign_up_spec.rb +0 -102
- data/spec/shared_examples/accessors.rb +0 -24
- data/spec/shared_examples/belongs_to.rb +0 -17
- data/spec/shared_examples/coercible_columns.rb +0 -248
- data/spec/shared_examples/constructor.rb +0 -30
- data/spec/shared_examples/defaults.rb +0 -60
- data/spec/shared_examples/dirty_tracking.rb +0 -40
- data/spec/shared_examples/dupable.rb +0 -31
- data/spec/shared_examples/mass_assignment.rb +0 -26
- data/spec/spec_helper.rb +0 -28
- data/spec/support/database.rb +0 -53
- data/spec/support/database.sample.yml +0 -3
- data/spec/support/error_on.rb +0 -12
- data/spec/support/i18n.rb +0 -1
- data/spec/support/protected_params.rb +0 -20
- data/spec/support/time_zone.rb +0 -1
@@ -1,274 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'ostruct'
|
3
|
-
|
4
|
-
module RecordSpec
|
5
|
-
|
6
|
-
def self.type
|
7
|
-
if ActiveRecord::VERSION::MAJOR >= 5
|
8
|
-
@type ||= ActiveModel::Type::Value.new
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
class Record < ActiveType::Record
|
13
|
-
|
14
|
-
attribute :virtual_string, :string
|
15
|
-
attribute :virtual_integer, :integer
|
16
|
-
attribute :virtual_time, :datetime
|
17
|
-
attribute :virtual_date, :date
|
18
|
-
attribute :virtual_boolean, :boolean
|
19
|
-
attribute :virtual_attribute
|
20
|
-
attribute :virtual_type_attribute, RecordSpec.type
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
class RecordWithValidations < Record
|
25
|
-
|
26
|
-
validates :persisted_string, :presence => true
|
27
|
-
validates :virtual_string, :presence => true
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
|
32
|
-
class RecordWithOverrides < Record
|
33
|
-
|
34
|
-
attribute :overridable_test, :string
|
35
|
-
|
36
|
-
def overridable_test
|
37
|
-
super + super
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
class RecordCopy < ActiveType::Record
|
43
|
-
self.table_name = 'records'
|
44
|
-
|
45
|
-
attribute :virtual_string, :string
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
class OtherRecord < ActiveType::Record
|
50
|
-
end
|
51
|
-
|
52
|
-
class Child < ActiveRecord::Base
|
53
|
-
end
|
54
|
-
|
55
|
-
class RecordWithBelongsTo < Record
|
56
|
-
|
57
|
-
attribute :child_id, :integer
|
58
|
-
|
59
|
-
belongs_to :child
|
60
|
-
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
|
65
|
-
describe ActiveType::Record do
|
66
|
-
|
67
|
-
subject { RecordSpec::Record.new }
|
68
|
-
t = Time.new(2016, 2, 1, 12)
|
69
|
-
|
70
|
-
it 'is a ActiveRecord::Base' do
|
71
|
-
expect(subject).to be_a(ActiveRecord::Base)
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'is an abstract class' do
|
75
|
-
expect(ActiveType::Record).to be_abstract_class
|
76
|
-
end
|
77
|
-
|
78
|
-
describe 'constructors' do
|
79
|
-
subject { RecordSpec::Record }
|
80
|
-
|
81
|
-
it_should_behave_like 'ActiveRecord-like constructors', { :persisted_string => "string", :persisted_integer => 100, :persisted_time => t, :persisted_date => Date.today, :persisted_boolean => true }
|
82
|
-
|
83
|
-
it_should_behave_like 'ActiveRecord-like constructors', { :virtual_string => "string", :virtual_integer => 100, :virtual_time => t, :virtual_date => Date.today, :virtual_boolean => true }
|
84
|
-
|
85
|
-
end
|
86
|
-
|
87
|
-
describe 'mass assignment' do
|
88
|
-
it_should_behave_like 'ActiveRecord-like mass assignment', { :persisted_string => "string", :persisted_integer => 100, :persisted_time => t, :persisted_date => Date.today, :persisted_boolean => true }
|
89
|
-
|
90
|
-
it_should_behave_like 'ActiveRecord-like mass assignment', { :virtual_string => "string", :virtual_integer => 100, :virtual_time => t, :virtual_date => Date.today, :virtual_boolean => true }
|
91
|
-
end
|
92
|
-
|
93
|
-
describe 'accessors' do
|
94
|
-
it_should_behave_like 'ActiveRecord-like accessors', { :persisted_string => "string", :persisted_integer => 100, :persisted_time => t, :persisted_date => Date.today, :persisted_boolean => true }
|
95
|
-
|
96
|
-
it_should_behave_like 'ActiveRecord-like accessors', { :virtual_string => "string", :virtual_integer => 100, :virtual_time => t, :virtual_date => Date.today, :virtual_boolean => true }
|
97
|
-
end
|
98
|
-
|
99
|
-
describe 'overridable attributes' do
|
100
|
-
|
101
|
-
subject { RecordSpec::RecordWithOverrides.new }
|
102
|
-
|
103
|
-
it 'is possible to override attributes with super' do
|
104
|
-
subject.overridable_test = "test"
|
105
|
-
|
106
|
-
expect(subject.overridable_test).to eq("testtest")
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
describe 'attribute name validation' do
|
111
|
-
it 'crashes when trying to define an invalid attribute name' do
|
112
|
-
klass = Class.new(ActiveType::Record)
|
113
|
-
expect {
|
114
|
-
klass.class_eval do
|
115
|
-
attribute :"<attr>", :string
|
116
|
-
end
|
117
|
-
}.to raise_error(ActiveType::InvalidAttributeNameError)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
describe '.reset_column_information' do
|
122
|
-
it 'does not affect virtual attributes' do
|
123
|
-
RecordSpec::RecordCopy.new.persisted_string = "string"
|
124
|
-
RecordSpec::RecordCopy.reset_column_information
|
125
|
-
|
126
|
-
expect do
|
127
|
-
RecordSpec::RecordCopy.new.virtual_string = "string"
|
128
|
-
end.to_not raise_error
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
context 'coercible' do
|
133
|
-
describe 'string columns' do
|
134
|
-
it_should_behave_like 'a coercible string column', :persisted_string
|
135
|
-
it_should_behave_like 'a coercible string column', :virtual_string
|
136
|
-
end
|
137
|
-
|
138
|
-
describe 'integer columns' do
|
139
|
-
it_should_behave_like 'a coercible integer column', :persisted_integer
|
140
|
-
it_should_behave_like 'a coercible integer column', :virtual_integer
|
141
|
-
end
|
142
|
-
|
143
|
-
describe 'date columns' do
|
144
|
-
it_should_behave_like 'a coercible date column', :persisted_date
|
145
|
-
it_should_behave_like 'a coercible date column', :virtual_date
|
146
|
-
end
|
147
|
-
|
148
|
-
describe 'time columns' do
|
149
|
-
it_should_behave_like 'a coercible time column', :persisted_time
|
150
|
-
it_should_behave_like 'a coercible time column', :virtual_time
|
151
|
-
end
|
152
|
-
|
153
|
-
describe 'boolean columns' do
|
154
|
-
it_should_behave_like 'a coercible boolean column', :persisted_boolean
|
155
|
-
it_should_behave_like 'a coercible boolean column', :virtual_boolean
|
156
|
-
end
|
157
|
-
|
158
|
-
describe 'untyped columns' do
|
159
|
-
it_should_behave_like 'an untyped column', :virtual_attribute
|
160
|
-
end
|
161
|
-
|
162
|
-
describe 'type columns' do
|
163
|
-
it_should_behave_like 'a coercible type column', :virtual_type_attribute, RecordSpec.type
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
describe '#inspect' do
|
168
|
-
|
169
|
-
it 'returns the contents of the object as a nicely formatted string' do
|
170
|
-
t = Time.now
|
171
|
-
subject.persisted_string = "persisted string"
|
172
|
-
subject.virtual_string = "string"
|
173
|
-
subject.persisted_integer = 20
|
174
|
-
subject.virtual_integer = 17
|
175
|
-
subject.virtual_time = t
|
176
|
-
subject.virtual_date = Date.today
|
177
|
-
subject.virtual_boolean = true
|
178
|
-
subject.virtual_attribute = OpenStruct.new({:test => "openstruct"})
|
179
|
-
|
180
|
-
expect(subject.inspect).to eq("#<RecordSpec::Record id: nil, persisted_boolean: nil, persisted_date: nil, persisted_integer: 20, persisted_string: \"persisted string\", persisted_time: nil, virtual_attribute: #<OpenStruct test=\"openstruct\">, virtual_boolean: true, virtual_date: \"#{Date.today}\", virtual_integer: 17, virtual_string: \"string\", virtual_time: \"#{t.to_s(:db)}\", virtual_type_attribute: nil>")
|
181
|
-
end
|
182
|
-
|
183
|
-
end
|
184
|
-
|
185
|
-
describe '#attributes' do
|
186
|
-
|
187
|
-
it 'returns a hash of virtual and persisted attributes' do
|
188
|
-
subject.persisted_string = "string"
|
189
|
-
subject.virtual_string = "string"
|
190
|
-
subject.virtual_integer = "17"
|
191
|
-
|
192
|
-
expect(subject.attributes).to eq({
|
193
|
-
"virtual_string" => "string",
|
194
|
-
"virtual_integer" => 17,
|
195
|
-
"virtual_time" => nil,
|
196
|
-
"virtual_date" => nil,
|
197
|
-
"virtual_boolean" => nil,
|
198
|
-
"virtual_attribute" => nil,
|
199
|
-
"virtual_type_attribute" => nil,
|
200
|
-
"id" => nil,
|
201
|
-
"persisted_string" => "string",
|
202
|
-
"persisted_integer" => nil,
|
203
|
-
"persisted_time" => nil,
|
204
|
-
"persisted_date" => nil,
|
205
|
-
"persisted_boolean" => nil,
|
206
|
-
})
|
207
|
-
end
|
208
|
-
|
209
|
-
end
|
210
|
-
|
211
|
-
describe 'validations' do
|
212
|
-
subject { RecordSpec::RecordWithValidations.new }
|
213
|
-
|
214
|
-
it 'has 1 error_on' do
|
215
|
-
expect(subject.error_on(:persisted_string).size).to eq(1)
|
216
|
-
end
|
217
|
-
it 'has 1 error_on' do
|
218
|
-
expect(subject.error_on(:virtual_string).size).to eq(1)
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
describe 'undefined columns' do
|
223
|
-
it 'raises an error when trying to access an undefined virtual attribute' do
|
224
|
-
expect do
|
225
|
-
subject.read_virtual_attribute('foo')
|
226
|
-
end.to raise_error(ActiveType::MissingAttributeError)
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
describe 'defaults' do
|
231
|
-
it_should_behave_like "a class accepting attribute defaults", RecordSpec::Record
|
232
|
-
end
|
233
|
-
|
234
|
-
describe 'duping' do
|
235
|
-
it_should_behave_like "a class supporting dup for attributes", RecordSpec::Record
|
236
|
-
end
|
237
|
-
|
238
|
-
describe 'dirty tracking' do
|
239
|
-
it_should_behave_like 'a class supporting dirty tracking for virtual attributes', RecordSpec::Record
|
240
|
-
end
|
241
|
-
|
242
|
-
describe 'persistence' do
|
243
|
-
|
244
|
-
it 'persists to the database' do
|
245
|
-
subject.persisted_string = "persisted string"
|
246
|
-
expect(subject.save).to eq(true)
|
247
|
-
|
248
|
-
expect(subject.class.find(subject.id).persisted_string).to eq("persisted string")
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
describe 'isolation' do
|
253
|
-
it 'does not let column information bleed into different models' do
|
254
|
-
record = RecordSpec::Record.new
|
255
|
-
other_record = RecordSpec::OtherRecord.new
|
256
|
-
|
257
|
-
expect(record).not_to respond_to(:other_string)
|
258
|
-
expect(other_record).not_to respond_to(:persisted_string)
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
describe '#belongs_to' do
|
263
|
-
subject { RecordSpec::RecordWithBelongsTo.new }
|
264
|
-
|
265
|
-
it_should_behave_like 'a belongs_to association', :child, RecordSpec::Child
|
266
|
-
end
|
267
|
-
|
268
|
-
it 'can access virtual attributes after .find' do
|
269
|
-
subject.save!
|
270
|
-
expect(subject.class.find(subject.id).virtual_string).to eq(nil)
|
271
|
-
expect(subject.class.find(subject.id).virtual_string).to eq(nil)
|
272
|
-
end
|
273
|
-
|
274
|
-
end
|
@@ -1,142 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module UtilSpec
|
4
|
-
|
5
|
-
class BaseRecord < ActiveRecord::Base
|
6
|
-
self.table_name = 'records'
|
7
|
-
end
|
8
|
-
|
9
|
-
class ExtendedRecord < ActiveType::Record[BaseRecord]
|
10
|
-
|
11
|
-
attribute :virtual_string
|
12
|
-
attribute :virtual_string_for_validation
|
13
|
-
after_initialize :set_virtual_string
|
14
|
-
attr_reader :after_initialize_called
|
15
|
-
|
16
|
-
def set_virtual_string
|
17
|
-
@after_initialize_called = true
|
18
|
-
self.virtual_string = "persisted_string is #{persisted_string}"
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
class Parent < ActiveRecord::Base
|
24
|
-
self.table_name = 'sti_records'
|
25
|
-
end
|
26
|
-
|
27
|
-
class Child < Parent
|
28
|
-
end
|
29
|
-
|
30
|
-
class ChildSibling < Parent
|
31
|
-
end
|
32
|
-
|
33
|
-
class ExtendedChild < ActiveType::Record[Child]
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
37
|
-
|
38
|
-
describe ActiveType::Util do
|
39
|
-
|
40
|
-
describe '.cast' do
|
41
|
-
|
42
|
-
describe 'for a relation' do
|
43
|
-
|
44
|
-
it 'casts a scope to a scope of another class' do
|
45
|
-
record = UtilSpec::BaseRecord.create!(:persisted_string => 'foo')
|
46
|
-
base_scope = UtilSpec::BaseRecord.where(:persisted_string => 'foo')
|
47
|
-
casted_scope = ActiveType::Util.cast(base_scope, UtilSpec::ExtendedRecord)
|
48
|
-
expect(casted_scope.build).to be_a(UtilSpec::ExtendedRecord)
|
49
|
-
found_record = casted_scope.find(record.id)
|
50
|
-
expect(found_record.persisted_string).to eq('foo')
|
51
|
-
expect(found_record).to be_a(UtilSpec::ExtendedRecord)
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'preserves existing scope conditions' do
|
55
|
-
match = UtilSpec::BaseRecord.create!(:persisted_string => 'foo')
|
56
|
-
no_match = UtilSpec::BaseRecord.create!(:persisted_string => 'bar')
|
57
|
-
base_scope = UtilSpec::BaseRecord.where(:persisted_string => 'foo')
|
58
|
-
casted_scope = ActiveType::Util.cast(base_scope, UtilSpec::ExtendedRecord)
|
59
|
-
casted_match = UtilSpec::ExtendedRecord.find(match.id)
|
60
|
-
expect(casted_scope.to_a).to eq([casted_match])
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|
64
|
-
|
65
|
-
describe 'for a record type' do
|
66
|
-
|
67
|
-
it 'casts a base record to an extended record' do
|
68
|
-
base_record = UtilSpec::BaseRecord.create!(:persisted_string => 'foo')
|
69
|
-
extended_record = ActiveType::Util.cast(base_record, UtilSpec::ExtendedRecord)
|
70
|
-
expect(extended_record).to be_a(UtilSpec::ExtendedRecord)
|
71
|
-
expect(extended_record).to be_persisted
|
72
|
-
expect(extended_record.id).to be_present
|
73
|
-
expect(extended_record.id).to eq(base_record.id)
|
74
|
-
expect(extended_record.persisted_string).to eq('foo')
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'casts an extended record to a base record' do
|
78
|
-
extended_record = UtilSpec::ExtendedRecord.create!(:persisted_string => 'foo')
|
79
|
-
base_record = ActiveType::Util.cast(extended_record, UtilSpec::BaseRecord)
|
80
|
-
expect(base_record).to be_a(UtilSpec::BaseRecord)
|
81
|
-
expect(base_record).to be_persisted
|
82
|
-
expect(base_record.id).to be_present
|
83
|
-
expect(base_record.id).to eq(extended_record.id)
|
84
|
-
expect(base_record.persisted_string).to eq('foo')
|
85
|
-
end
|
86
|
-
|
87
|
-
it 'calls after_initialize callbacks of the cast target' do
|
88
|
-
base_record = UtilSpec::BaseRecord.create!(:persisted_string => 'foo')
|
89
|
-
extended_record = ActiveType::Util.cast(base_record, UtilSpec::ExtendedRecord)
|
90
|
-
expect(extended_record.after_initialize_called).to eq true
|
91
|
-
end
|
92
|
-
|
93
|
-
it 'lets after_initialize callbacks access attributes (bug in ActiveRecord#becomes)' do
|
94
|
-
base_record = UtilSpec::BaseRecord.create!(:persisted_string => 'foo')
|
95
|
-
extended_record = ActiveType::Util.cast(base_record, UtilSpec::ExtendedRecord)
|
96
|
-
expect(extended_record.virtual_string).to eq('persisted_string is foo')
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'preserves the #type of an STI record that is casted to an ExtendedRecord' do
|
100
|
-
child_record = UtilSpec::Child.create!(:persisted_string => 'foo')
|
101
|
-
extended_child_record = ActiveType::Util.cast(child_record, UtilSpec::ExtendedChild)
|
102
|
-
expect(extended_child_record).to be_a(UtilSpec::ExtendedChild)
|
103
|
-
expect(extended_child_record.type).to eq('UtilSpec::Child')
|
104
|
-
end
|
105
|
-
|
106
|
-
it 'changes the #type of an STI record when casted to another type in the hierarchy' do
|
107
|
-
child_record = UtilSpec::Child.create!(:persisted_string => 'foo')
|
108
|
-
child_sibling_record = ActiveType::Util.cast(child_record, UtilSpec::ChildSibling)
|
109
|
-
expect(child_sibling_record).to be_a(UtilSpec::ChildSibling)
|
110
|
-
expect(child_sibling_record.type).to eq('UtilSpec::Child')
|
111
|
-
end
|
112
|
-
|
113
|
-
it 'preserves dirty tracking flags' do
|
114
|
-
base_record = UtilSpec::BaseRecord.create!(:persisted_string => 'foo')
|
115
|
-
expect(base_record.changes).to eq({})
|
116
|
-
base_record.persisted_string = 'bar'
|
117
|
-
expect(base_record.changes).to eq({ 'persisted_string' => ['foo', 'bar'] })
|
118
|
-
extended_record = ActiveType::Util.cast(base_record, UtilSpec::ExtendedRecord)
|
119
|
-
expect(extended_record).to be_a(UtilSpec::ExtendedRecord)
|
120
|
-
expect(extended_record.changes).to eq({ 'persisted_string' => ['foo', 'bar'] })
|
121
|
-
end
|
122
|
-
|
123
|
-
it 'associates the error object correctly with the new type (BUGFIX)' do
|
124
|
-
base_record = UtilSpec::BaseRecord.create!(:persisted_string => 'foo')
|
125
|
-
extended_record = ActiveType::Util.cast(base_record, UtilSpec::ExtendedRecord)
|
126
|
-
expect {
|
127
|
-
value = extended_record.virtual_string_for_validation
|
128
|
-
extended_record.errors.add(:virtual_string_for_validation, :empty) if value.nil? || value.empty?
|
129
|
-
}.not_to raise_error
|
130
|
-
expect(extended_record.errors.size).to eq 1
|
131
|
-
expect(base_record.errors.size).to eq 0
|
132
|
-
end
|
133
|
-
|
134
|
-
end
|
135
|
-
|
136
|
-
end
|
137
|
-
|
138
|
-
it "exposes all methods through ActiveType's root namespace" do
|
139
|
-
expect(ActiveType).to respond_to(:cast)
|
140
|
-
end
|
141
|
-
|
142
|
-
end
|
@@ -1,102 +0,0 @@
|
|
1
|
-
# Usecase: CRUD a number of records
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
ActiveRecord::Migration.class_eval do
|
6
|
-
create_table :holidays do |t|
|
7
|
-
t.string :name
|
8
|
-
t.date :date
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
module HolidaySpec
|
13
|
-
|
14
|
-
class Holiday < ActiveRecord::Base
|
15
|
-
validates :name, :date, :presence => true
|
16
|
-
end
|
17
|
-
|
18
|
-
class HolidayForm < ActiveType::Object
|
19
|
-
nests_many :holidays, :scope => Holiday, :default => proc { Holiday.all }, :reject_if => :all_blank, :allow_destroy => true
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
|
25
|
-
describe HolidaySpec::HolidayForm do
|
26
|
-
|
27
|
-
let(:params) do
|
28
|
-
{
|
29
|
-
'1' => {
|
30
|
-
'name' => 'New Year',
|
31
|
-
'date' => '2014-01-01',
|
32
|
-
},
|
33
|
-
'2' => {
|
34
|
-
'name' => 'Epiphany',
|
35
|
-
'date' => '2014-01-06',
|
36
|
-
},
|
37
|
-
}
|
38
|
-
end
|
39
|
-
|
40
|
-
def update(params)
|
41
|
-
form = HolidaySpec::HolidayForm.new(:holidays_attributes => params)
|
42
|
-
if form.save
|
43
|
-
ids = form.holidays.collect(&:id)
|
44
|
-
params.each_with_index do |(key, attributes), index|
|
45
|
-
attributes['id'] = ids[index]
|
46
|
-
end
|
47
|
-
true
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'will return holidays including updated ones' do
|
52
|
-
HolidaySpec::Holiday.create!(:name => 'New Year', :date => '2014-01-01')
|
53
|
-
form = HolidaySpec::HolidayForm.new(:holidays_attributes => params.slice('2'))
|
54
|
-
expect(form.holidays.collect(&:name)).to eq(["New Year", "Epiphany"])
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'can create a list of holidays' do
|
58
|
-
expect(update(params)).to eq(true)
|
59
|
-
|
60
|
-
holidays = HolidaySpec::Holiday.order(:date)
|
61
|
-
expect(holidays.collect(&:name)).to eq(["New Year", "Epiphany"])
|
62
|
-
expect(holidays.collect(&:date)).to eq([Date.civil(2014, 1, 1), Date.civil(2014, 1, 6)])
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'can update holidays' do
|
66
|
-
update(params)
|
67
|
-
|
68
|
-
params['1']['name'] += ' 2014'
|
69
|
-
params['2']['name'] += ' 2014'
|
70
|
-
expect(update(params)).to eq(true)
|
71
|
-
|
72
|
-
holidays = HolidaySpec::Holiday.order(:date)
|
73
|
-
expect(holidays.collect(&:name)).to eq(["New Year 2014", "Epiphany 2014"])
|
74
|
-
expect(holidays.collect(&:date)).to eq([Date.civil(2014, 1, 1), Date.civil(2014, 1, 6)])
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'can destroy holidays' do
|
78
|
-
update(params)
|
79
|
-
|
80
|
-
params['1']['_destroy'] = '1'
|
81
|
-
expect(update(params)).to eq(true)
|
82
|
-
|
83
|
-
holidays = HolidaySpec::Holiday.order(:date)
|
84
|
-
expect(holidays.collect(&:name)).to eq(["Epiphany"])
|
85
|
-
expect(holidays.collect(&:date)).to eq([Date.civil(2014, 1, 6)])
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'will not save if some fields are invalid' do
|
89
|
-
update(params)
|
90
|
-
|
91
|
-
params['1']['name'] = '-'
|
92
|
-
params['1']['_destroy'] = '1'
|
93
|
-
params['2']['name'] = '' # invalid
|
94
|
-
expect(update(params)).to be_falsey
|
95
|
-
|
96
|
-
holidays = HolidaySpec::Holiday.order(:date)
|
97
|
-
expect(holidays.collect(&:name)).to eq(["New Year", "Epiphany"])
|
98
|
-
expect(holidays.collect(&:date)).to eq([Date.civil(2014, 1, 1), Date.civil(2014, 1, 6)])
|
99
|
-
end
|
100
|
-
|
101
|
-
|
102
|
-
end
|
@@ -1,110 +0,0 @@
|
|
1
|
-
# Usecase: Create a STI record, form model decides which type
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
ActiveRecord::Migration.class_eval do
|
6
|
-
create_table :shapes do |t|
|
7
|
-
t.string :type
|
8
|
-
t.integer :radius
|
9
|
-
t.integer :length
|
10
|
-
t.integer :width
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
module ShapeSpec
|
15
|
-
|
16
|
-
class Shape < ActiveType::Record
|
17
|
-
end
|
18
|
-
|
19
|
-
class Circle < Shape
|
20
|
-
validates :radius, :presence => true
|
21
|
-
end
|
22
|
-
|
23
|
-
class Rectangle < Shape
|
24
|
-
validates :length, :width, :presence => true
|
25
|
-
end
|
26
|
-
|
27
|
-
class ShapeForm < ActiveType::Object
|
28
|
-
nests_one :child
|
29
|
-
|
30
|
-
def child_type=(type)
|
31
|
-
case type
|
32
|
-
when 'circle'
|
33
|
-
if child
|
34
|
-
self.child = self.child.becomes(Circle)
|
35
|
-
else
|
36
|
-
self.child = Circle.new
|
37
|
-
end
|
38
|
-
when 'rectangle'
|
39
|
-
if child
|
40
|
-
self.child = self.child.becomes(Rectangle)
|
41
|
-
else
|
42
|
-
self.child = Rectangle.new
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
49
|
-
|
50
|
-
|
51
|
-
describe ShapeSpec::ShapeForm do
|
52
|
-
|
53
|
-
let(:form) { ShapeSpec::ShapeForm.new }
|
54
|
-
|
55
|
-
def update(params)
|
56
|
-
form.child_type = params[:type]
|
57
|
-
form.child_attributes = params.except(:type)
|
58
|
-
form.save
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'can create a circle' do
|
62
|
-
params = {
|
63
|
-
'type' => 'circle',
|
64
|
-
'radius' => '20'
|
65
|
-
}.with_indifferent_access
|
66
|
-
|
67
|
-
expect(update(params)).to eq(true)
|
68
|
-
|
69
|
-
expect(ShapeSpec::Circle.all.collect(&:radius)).to eq([20])
|
70
|
-
expect(ShapeSpec::Rectangle.count).to eq(0)
|
71
|
-
end
|
72
|
-
|
73
|
-
it 'can create a rectangle' do
|
74
|
-
params = {
|
75
|
-
'type' => 'rectangle',
|
76
|
-
'length' => '100',
|
77
|
-
'width' => '30'
|
78
|
-
}.with_indifferent_access
|
79
|
-
|
80
|
-
expect(update(params)).to eq(true)
|
81
|
-
|
82
|
-
expect(ShapeSpec::Circle.count).to eq(0)
|
83
|
-
expect(ShapeSpec::Rectangle.all.collect(&:length)).to eq([100])
|
84
|
-
expect(ShapeSpec::Rectangle.all.collect(&:width)).to eq([30])
|
85
|
-
end
|
86
|
-
|
87
|
-
it 'can update' do
|
88
|
-
params = {
|
89
|
-
'type' => 'circle',
|
90
|
-
'radius' => '20'
|
91
|
-
}.with_indifferent_access
|
92
|
-
update(params)
|
93
|
-
|
94
|
-
params['radius'] = '30'
|
95
|
-
expect(update(params)).to eq(true)
|
96
|
-
|
97
|
-
expect(ShapeSpec::Circle.all.collect(&:radius)).to eq([30])
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'has validations' do
|
101
|
-
params = {
|
102
|
-
'type' => 'circle'
|
103
|
-
}.with_indifferent_access
|
104
|
-
|
105
|
-
expect(update(params)).to be_falsey
|
106
|
-
|
107
|
-
expect(form.child.errors['radius']).to eq(["can't be blank"])
|
108
|
-
end
|
109
|
-
|
110
|
-
end
|