can_be 0.1.0 → 0.2.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.
- data/.travis.yml +5 -0
- data/.yardopts +4 -0
- data/CHANGELOG.md +7 -0
- data/README.md +93 -27
- data/can_be.gemspec +2 -2
- data/gemfiles/3.1.gemfile +7 -0
- data/gemfiles/3.2.gemfile +7 -0
- data/lib/can_be.rb +3 -1
- data/lib/can_be/builder.rb +7 -0
- data/lib/can_be/builder/can_be.rb +106 -0
- data/lib/can_be/builder/can_be_detail.rb +22 -0
- data/lib/can_be/config.rb +33 -0
- data/lib/can_be/model_extensions.rb +13 -1
- data/lib/can_be/processor.rb +7 -0
- data/lib/can_be/processor/instance.rb +61 -0
- data/lib/can_be/processor/klass.rb +36 -0
- data/lib/can_be/version.rb +1 -1
- data/spec/can_be/config_spec.rb +62 -0
- data/spec/can_be/model_extensions_spec.rb +391 -0
- data/spec/support/models.rb +28 -0
- data/spec/support/schema.rb +35 -0
- metadata +28 -8
- data/lib/can_be/initializer.rb +0 -90
- data/spec/can_be/model_additions_spec.rb +0 -173
@@ -0,0 +1,36 @@
|
|
1
|
+
module CanBe
|
2
|
+
module Processor
|
3
|
+
class Klass
|
4
|
+
def initialize(klass)
|
5
|
+
@klass = klass
|
6
|
+
@config = @klass.can_be_config
|
7
|
+
@field_name = @config.field_name
|
8
|
+
end
|
9
|
+
|
10
|
+
def find_by_types(*types)
|
11
|
+
@klass.where(@field_name => types)
|
12
|
+
end
|
13
|
+
|
14
|
+
def create(t, *args, &block)
|
15
|
+
set_field_on(args, t)
|
16
|
+
|
17
|
+
@klass.create(*args, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def instantiate(t, *args, &block)
|
21
|
+
set_field_on(args, t)
|
22
|
+
|
23
|
+
@klass.new(*args, &block)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def set_field_on(args, type)
|
28
|
+
if args[0]
|
29
|
+
args[0][@field_name.to_sym] = type
|
30
|
+
else
|
31
|
+
args[0] = { @field_name.to_sym => type }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/can_be/version.rb
CHANGED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CanBe::Config do
|
4
|
+
context "#field_name" do
|
5
|
+
it "defines a default field name" do
|
6
|
+
subject.field_name.should == :can_be_type
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
context "#types" do
|
11
|
+
it "converts the array to string values" do
|
12
|
+
subject.types = [:a, :b, :c]
|
13
|
+
subject.types.should == ["a", "b", "c"]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "#default_type" do
|
18
|
+
before :each do
|
19
|
+
subject.types = [:a, :b, :c]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns the first type by default" do
|
23
|
+
subject.default_type.should == "a"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "#parse_options" do
|
28
|
+
let(:field_name) { :example_field_name }
|
29
|
+
let(:default_type) { :example_default_type }
|
30
|
+
|
31
|
+
before :each do
|
32
|
+
subject.types = [:a, :b, :c]
|
33
|
+
|
34
|
+
subject.parse_options({
|
35
|
+
field_name: field_name,
|
36
|
+
default_type: default_type
|
37
|
+
})
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns the correct field_name" do
|
41
|
+
subject.field_name.should == field_name
|
42
|
+
end
|
43
|
+
|
44
|
+
it "returns the correct default_type" do
|
45
|
+
subject.default_type.should == default_type.to_s
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "#add_detail_model" do
|
50
|
+
it "adds the detail information" do
|
51
|
+
CanBe::Config.add_detail_model ConfigSpecDetail, :config_spec_model, :type1
|
52
|
+
ConfigSpecModel.can_be_config.details[:type1].should == ConfigSpecDetail.name
|
53
|
+
end
|
54
|
+
|
55
|
+
it "adds the detail information for a second record" do
|
56
|
+
CanBe::Config.add_detail_model ConfigSpecDetail, :config_spec_model, :type1
|
57
|
+
CanBe::Config.add_detail_model ConfigSpecDetail2, :config_spec_model, :type2
|
58
|
+
ConfigSpecModel.can_be_config.details[:type2].should == ConfigSpecDetail2.name
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
@@ -0,0 +1,391 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CanBe::ModelExtensions do
|
4
|
+
context "#can_be" do
|
5
|
+
context "instance methods" do
|
6
|
+
describe "boolean record methods" do
|
7
|
+
it "are created" do
|
8
|
+
rec = new_address
|
9
|
+
rec.should respond_to :home_address?
|
10
|
+
rec.should respond_to :work_address?
|
11
|
+
end
|
12
|
+
|
13
|
+
it "responds true" do
|
14
|
+
new_address(:home_address).should be_home_address
|
15
|
+
new_address(:work_address).should be_work_address
|
16
|
+
end
|
17
|
+
|
18
|
+
it "responds false" do
|
19
|
+
new_address(:work_address).should_not be_home_address
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "change_to methods" do
|
24
|
+
it "are created" do
|
25
|
+
rec = new_address
|
26
|
+
rec.should respond_to :change_to_home_address
|
27
|
+
rec.should respond_to :change_to_work_address
|
28
|
+
end
|
29
|
+
|
30
|
+
it "updates the record" do
|
31
|
+
rec = new_address(:work_address)
|
32
|
+
rec.change_to_home_address
|
33
|
+
rec.should be_home_address
|
34
|
+
end
|
35
|
+
|
36
|
+
it "does not update the database" do
|
37
|
+
rec = create_address(:work_address)
|
38
|
+
rec.change_to_home_address
|
39
|
+
Address.first.should_not be_home_address
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "change_to! methods" do
|
44
|
+
it "are created" do
|
45
|
+
rec = create_address
|
46
|
+
rec.should respond_to :change_to_home_address!
|
47
|
+
rec.should respond_to :change_to_work_address!
|
48
|
+
end
|
49
|
+
|
50
|
+
it "updates the record" do
|
51
|
+
rec = create_address(:work_address)
|
52
|
+
rec.change_to_home_address!
|
53
|
+
rec.should be_home_address
|
54
|
+
end
|
55
|
+
|
56
|
+
it "updates the database" do
|
57
|
+
rec = create_address(:work_address)
|
58
|
+
rec.change_to_home_address!
|
59
|
+
Address.first.should be_home_address
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "class methods" do
|
65
|
+
describe "create methods" do
|
66
|
+
it "are created" do
|
67
|
+
Address.should respond_to :create_home_address
|
68
|
+
Address.should respond_to :create_work_address
|
69
|
+
end
|
70
|
+
|
71
|
+
it "create the records in the database" do
|
72
|
+
a = Address.create_home_address
|
73
|
+
Address.find(a.id).should be_home_address
|
74
|
+
|
75
|
+
a = Address.create_work_address
|
76
|
+
Address.find(a.id).should be_work_address
|
77
|
+
end
|
78
|
+
|
79
|
+
it "creates the record in the database with the other data stored" do
|
80
|
+
a = Address.create_home_address city: 'home city'
|
81
|
+
Address.find(a.id).city.should == 'home city'
|
82
|
+
end
|
83
|
+
|
84
|
+
it "creates the records changing to the correct type" do
|
85
|
+
a = Address.create_home_address can_be_type: 'work_address'
|
86
|
+
Address.find(a.id).should be_home_address
|
87
|
+
end
|
88
|
+
|
89
|
+
it "processes the create 'do' block correctly" do
|
90
|
+
city = "Philadelphia"
|
91
|
+
a = Address.create_home_address do |address|
|
92
|
+
address.city = city
|
93
|
+
end
|
94
|
+
a.city.should == city
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "new methods" do
|
99
|
+
it "are created" do
|
100
|
+
Address.should respond_to :new_home_address
|
101
|
+
Address.should respond_to :new_work_address
|
102
|
+
end
|
103
|
+
|
104
|
+
it "create the correct type" do
|
105
|
+
Address.new_home_address.should be_home_address
|
106
|
+
Address.new_work_address.should be_work_address
|
107
|
+
end
|
108
|
+
|
109
|
+
it "stores the other data field correctly" do
|
110
|
+
Address.new_home_address(city: 'home city').city.should == 'home city'
|
111
|
+
end
|
112
|
+
|
113
|
+
it "create the records changing to the correct type" do
|
114
|
+
Address.create_home_address(can_be_type: 'work_address').should be_home_address
|
115
|
+
end
|
116
|
+
|
117
|
+
it "don't create the records in the database" do
|
118
|
+
Address.new_home_address
|
119
|
+
Address.new_work_address
|
120
|
+
Address.count.should == 0
|
121
|
+
end
|
122
|
+
|
123
|
+
it "processes the new 'do' block correctly" do
|
124
|
+
city = "Philadelphia"
|
125
|
+
a = Address.new_home_address do |address|
|
126
|
+
address.city = city
|
127
|
+
end
|
128
|
+
a.city.should == city
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "finder methods" do
|
133
|
+
let(:home_count) { 5 }
|
134
|
+
let(:work_count) { 4 }
|
135
|
+
let(:vacation_count) { 3 }
|
136
|
+
|
137
|
+
before :each do
|
138
|
+
home_count.times { Address.create_home_address }
|
139
|
+
work_count.times { Address.create_work_address }
|
140
|
+
vacation_count.times { Address.create_vacation_address }
|
141
|
+
end
|
142
|
+
|
143
|
+
it "are created" do
|
144
|
+
Address.should respond_to :find_by_can_be_types
|
145
|
+
Address.should respond_to 'home_address'.pluralize
|
146
|
+
Address.should respond_to 'work_address'.pluralize
|
147
|
+
end
|
148
|
+
|
149
|
+
it "#find_by_can_be_types returns the correct records" do
|
150
|
+
recs = Address.find_by_can_be_types(:home_address, :work_address)
|
151
|
+
recs.should have(home_count + work_count).items
|
152
|
+
recs.each do |a|
|
153
|
+
a.can_be_type.should =~ /^home_address|work_address$/
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
it "returns the correct records" do
|
158
|
+
recs = Address.home_addresses
|
159
|
+
recs.should have(home_count).items
|
160
|
+
recs.each { |a| a.should be_home_address }
|
161
|
+
|
162
|
+
recs = Address.work_addresses
|
163
|
+
recs.should have(work_count).items
|
164
|
+
recs.each { |a| a.should be_work_address }
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context "default type" do
|
170
|
+
it "uses the first type as the default" do
|
171
|
+
Address.new.should be_home_address
|
172
|
+
end
|
173
|
+
|
174
|
+
it "uses the specified default_type option" do
|
175
|
+
Person.new.should be_female
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context "database field" do
|
180
|
+
it "uses the :can_be_type field (default)" do
|
181
|
+
Address.new_home_address.can_be_type.should == 'home_address'
|
182
|
+
end
|
183
|
+
|
184
|
+
it "uses the specified field" do
|
185
|
+
Person.new_female.gender.should == 'female'
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context "validity of type value" do
|
190
|
+
it "should be valid" do
|
191
|
+
Address.new_home_address.should be_valid
|
192
|
+
Address.new_work_address.should be_valid
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should not be valid" do
|
196
|
+
Address.new(can_be_type: 'invalid type').should_not be_valid
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
context "details" do
|
201
|
+
context "persistence" do
|
202
|
+
it "persists the details information to the database (create method)" do
|
203
|
+
upload = Upload.create
|
204
|
+
upload.details.format = "jpeg"
|
205
|
+
upload.save
|
206
|
+
ImageUploadDetail.first.format.should == "jpeg"
|
207
|
+
end
|
208
|
+
|
209
|
+
it "persists the details information to the database (create_image_upload method)" do
|
210
|
+
upload = Upload.create_image_upload
|
211
|
+
upload.details.format = "jpeg"
|
212
|
+
upload.save
|
213
|
+
ImageUploadDetail.first.format.should == "jpeg"
|
214
|
+
end
|
215
|
+
|
216
|
+
it "persists the details information to the database (new method)" do
|
217
|
+
upload = Upload.new
|
218
|
+
upload.details.format = "jpeg"
|
219
|
+
upload.save
|
220
|
+
ImageUploadDetail.first.format.should == "jpeg"
|
221
|
+
end
|
222
|
+
|
223
|
+
it "persists the details information to the database (new_image_upload method)" do
|
224
|
+
upload = Upload.new_image_upload
|
225
|
+
upload.details.format = "jpeg"
|
226
|
+
upload.save
|
227
|
+
ImageUploadDetail.first.format.should == "jpeg"
|
228
|
+
end
|
229
|
+
|
230
|
+
it "persists only one details record" do
|
231
|
+
upload = Upload.new
|
232
|
+
upload.details.format = "jpeg"
|
233
|
+
upload.save
|
234
|
+
found_upload = Upload.find(upload.id)
|
235
|
+
found_upload.details.format.should == "jpeg"
|
236
|
+
found_upload.save
|
237
|
+
ImageUploadDetail.count.should == 1
|
238
|
+
end
|
239
|
+
|
240
|
+
it "deletes the details record" do
|
241
|
+
u = Upload.create_image_upload
|
242
|
+
ImageUploadDetail.count.should == 1
|
243
|
+
u.destroy
|
244
|
+
ImageUploadDetail.count.should == 0
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
context "create method" do
|
249
|
+
it "creates the correct details record" do
|
250
|
+
Upload.create_image_upload.details.should be_instance_of(ImageUploadDetail)
|
251
|
+
Upload.create_video_upload.details.should be_instance_of(VideoUploadDetail)
|
252
|
+
end
|
253
|
+
|
254
|
+
it "doesn't create details record if model doesn't call #can_be_detail" do
|
255
|
+
Upload.create_thumbnail_upload.details.should be_nil
|
256
|
+
end
|
257
|
+
|
258
|
+
it "doesn't create details record if model doesn't exist" do
|
259
|
+
Upload.create_pdf_upload.details.should be_nil
|
260
|
+
end
|
261
|
+
|
262
|
+
it "doesn't create details record unless an ActiveRecord model" do
|
263
|
+
Upload.create_document_upload.details.should be_nil
|
264
|
+
end
|
265
|
+
|
266
|
+
it "persists the details record to the database" do
|
267
|
+
Upload.create_image_upload
|
268
|
+
ImageUploadDetail.count.should == 1
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
context "new method" do
|
273
|
+
it "instantiates the correct details record" do
|
274
|
+
Upload.new_image_upload.details.should be_instance_of(ImageUploadDetail)
|
275
|
+
Upload.new_video_upload.details.should be_instance_of(VideoUploadDetail)
|
276
|
+
end
|
277
|
+
|
278
|
+
it "doesn't instantiate details record if model doesn't call #can_be_detail" do
|
279
|
+
Upload.new_thumbnail_upload.details.should be_nil
|
280
|
+
end
|
281
|
+
|
282
|
+
it "doesn't instantiate details record if model doesn't exist" do
|
283
|
+
Upload.new_pdf_upload.details.should be_nil
|
284
|
+
end
|
285
|
+
|
286
|
+
it "doesn't instantiate details record unless an ActiveRecord model" do
|
287
|
+
Upload.new_document_upload.details.should be_nil
|
288
|
+
end
|
289
|
+
|
290
|
+
it "doesn't persist the details record to the database" do
|
291
|
+
Upload.new_image_upload
|
292
|
+
ImageUploadDetail.count.should == 0
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
context "change type via #change_to" do
|
297
|
+
it "changes the details record type" do
|
298
|
+
u = Upload.new_image_upload
|
299
|
+
u.change_to_video_upload
|
300
|
+
u.details.should be_instance_of(VideoUploadDetail)
|
301
|
+
end
|
302
|
+
|
303
|
+
it "changes the details to nil" do
|
304
|
+
u = Upload.new_image_upload
|
305
|
+
u.change_to_thumbnail_upload
|
306
|
+
u.details.should be_nil
|
307
|
+
end
|
308
|
+
|
309
|
+
it "doesn't create a new record in the database" do
|
310
|
+
u = Upload.new_image_upload
|
311
|
+
u.change_to_video_upload
|
312
|
+
ImageUploadDetail.count.should == 0
|
313
|
+
VideoUploadDetail.count.should == 0
|
314
|
+
end
|
315
|
+
|
316
|
+
it "has access to the original details if not saved" do
|
317
|
+
u = Upload.create_image_upload
|
318
|
+
u.change_to_video_upload
|
319
|
+
Upload.find(u.id).details.should be_instance_of(ImageUploadDetail)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
context "change type via #change_to!" do
|
324
|
+
it "changes the details record type" do
|
325
|
+
u = Upload.create_video_upload
|
326
|
+
u.change_to_image_upload!
|
327
|
+
Upload.find(u.id).details.should be_instance_of(ImageUploadDetail)
|
328
|
+
end
|
329
|
+
|
330
|
+
it "changes the details to nil" do
|
331
|
+
u = Upload.create_image_upload
|
332
|
+
u.change_to_thumbnail_upload!
|
333
|
+
Upload.find(u.id).details.should be_nil
|
334
|
+
end
|
335
|
+
|
336
|
+
it "doesn't create a new record in the database" do
|
337
|
+
u = Upload.create_video_upload
|
338
|
+
u.change_to_image_upload!
|
339
|
+
ImageUploadDetail.count.should == 1
|
340
|
+
end
|
341
|
+
|
342
|
+
it "removes the old database record from the database" do
|
343
|
+
u = Upload.create_image_upload
|
344
|
+
u.change_to_video_upload!
|
345
|
+
ImageUploadDetail.count.should == 0
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
context "change type setting the model attribute" do
|
350
|
+
it "changes the details record type" do
|
351
|
+
u = Upload.new_image_upload
|
352
|
+
u.can_be_type = "video_upload"
|
353
|
+
u.details.should be_instance_of(VideoUploadDetail)
|
354
|
+
end
|
355
|
+
|
356
|
+
it "changes the details to nil" do
|
357
|
+
u = Upload.new_image_upload
|
358
|
+
u.can_be_type = "thumbnail_upload"
|
359
|
+
u.details.should be_nil
|
360
|
+
end
|
361
|
+
|
362
|
+
it "doesn't create a new record in the database" do
|
363
|
+
u = Upload.new_image_upload
|
364
|
+
u.can_be_type = "video_upload"
|
365
|
+
ImageUploadDetail.count.should == 0
|
366
|
+
VideoUploadDetail.count.should == 0
|
367
|
+
end
|
368
|
+
|
369
|
+
it "has access to the original details if not saved" do
|
370
|
+
u = Upload.create_image_upload
|
371
|
+
u.can_be_type = "video_upload"
|
372
|
+
Upload.find(u.id).details.should be_instance_of(ImageUploadDetail)
|
373
|
+
end
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
context "#can_be_details" do
|
379
|
+
it "implements has_one to the can_be model" do
|
380
|
+
u = Upload.create_image_upload
|
381
|
+
ImageUploadDetail.first.upload.should == u
|
382
|
+
end
|
383
|
+
|
384
|
+
it "deletes the can_be model" do
|
385
|
+
Upload.create_image_upload
|
386
|
+
Upload.count.should == 1
|
387
|
+
ImageUploadDetail.first.destroy
|
388
|
+
Upload.count.should == 0
|
389
|
+
end
|
390
|
+
end
|
391
|
+
end
|