motion_model 0.3.8 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +10 -0
- data/README.md +31 -1
- data/lib/motion_model/adapters/array_model_adapter.rb +145 -0
- data/lib/motion_model/model/{finder_query.rb → array_finder_query.rb} +1 -1
- data/lib/motion_model/model/formotion.rb +1 -1
- data/lib/motion_model/model/model.rb +32 -124
- data/lib/motion_model/version.rb +6 -2
- data/spec/cascading_delete_spec.rb +5 -0
- data/spec/column_options_spec.rb +1 -0
- data/spec/date_spec.rb +2 -0
- data/spec/finder_spec.rb +5 -3
- data/spec/formotion_spec.rb +2 -0
- data/spec/model_casting_spec.rb +1 -0
- data/spec/model_hook_spec.rb +2 -1
- data/spec/model_spec.rb +13 -1
- data/spec/notification_spec.rb +1 -0
- data/spec/persistence_spec.rb +8 -0
- data/spec/relation_spec.rb +4 -0
- data/spec/transaction_spec.rb +2 -0
- data/spec/validation_spec.rb +3 -1
- metadata +4 -3
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
2012-02-19: Included Doug Puchalski's great refactoring of Model that provides an
|
2
|
+
adapter for ArrayModelAdapter. WARNING!!! This is a breaking change
|
3
|
+
since version 0.3.8. You will have to include:
|
4
|
+
|
5
|
+
MotionModel::ArrayModelAdapter
|
6
|
+
|
7
|
+
after including MotionModel::Model to get the same functionality.
|
8
|
+
Failure to include an adapter (note: spelling counts :) will result
|
9
|
+
in an exception so this will not quietly fail.
|
10
|
+
|
1
11
|
2012-01-24: Added block-structured transactions.
|
2
12
|
|
3
13
|
2012-01-14: Fixed problem where data returned from forms was of type NSString, which
|
data/README.md
CHANGED
@@ -31,6 +31,36 @@ you like with it. See the LICENSE file in this project.
|
|
31
31
|
* [Problems/Comments](#problemscomments)
|
32
32
|
* [Submissions/Patches](#submissionspatches)
|
33
33
|
|
34
|
+
Most Recent Important Change
|
35
|
+
=================
|
36
|
+
|
37
|
+
Please see the CHANGELOG for update on changes.
|
38
|
+
|
39
|
+
Version 0.3.8 to 0.4.0 is a minor version bump, not a patch version. Upgrading
|
40
|
+
to 0.4.0 *will break existing code*. To update your code, simply insert the following line:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
class ModelWithAdapter
|
44
|
+
include MotionModel::Model
|
45
|
+
include MotionModel::ArrayModelAdapter # <== Here!
|
46
|
+
|
47
|
+
columns :name
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
This change lays the foundation for using other persistence adapters.
|
52
|
+
If you don't want to update all your models, install the gem:
|
53
|
+
|
54
|
+
```
|
55
|
+
$ gem install motion_model -v 0.3.8
|
56
|
+
```
|
57
|
+
|
58
|
+
or if you are using bundler:
|
59
|
+
|
60
|
+
```
|
61
|
+
gem motion_model, "0.3.8"
|
62
|
+
```
|
63
|
+
|
34
64
|
Getting Going
|
35
65
|
================
|
36
66
|
|
@@ -200,7 +230,7 @@ You must return `true` from your validator if the value passes validation otherw
|
|
200
230
|
An important note about `save` once you include `Validatable`, you have two flavors
|
201
231
|
of save:
|
202
232
|
|
203
|
-
Method | Meaning
|
233
|
+
Method | Meaning
|
204
234
|
-----------------------|---------------------------
|
205
235
|
`save(options)` |Just saves the data if it is valid (passes validations) or if you have specified `:validate => false`
|
206
236
|
`save!` |Saves the data if it is valid, otherwise raises a `MotionModel::Validatable::RecordInvalid` exception
|
@@ -0,0 +1,145 @@
|
|
1
|
+
module MotionModel
|
2
|
+
module ArrayModelAdapter
|
3
|
+
def adapter
|
4
|
+
'Array Model Adapter'
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(PrivateClassMethods)
|
9
|
+
base.extend(PublicClassMethods)
|
10
|
+
base.instance_variable_set("@collection", []) # Actual data
|
11
|
+
end
|
12
|
+
|
13
|
+
module PublicClassMethods
|
14
|
+
|
15
|
+
def collection
|
16
|
+
@collection ||= []
|
17
|
+
end
|
18
|
+
|
19
|
+
def insert(object)
|
20
|
+
collection << object
|
21
|
+
end
|
22
|
+
|
23
|
+
def length
|
24
|
+
collection.length
|
25
|
+
end
|
26
|
+
alias_method :count, :length
|
27
|
+
|
28
|
+
# Deletes all rows in the model -- no hooks are called and
|
29
|
+
# deletes are not cascading so this does not affected related
|
30
|
+
# data.
|
31
|
+
def delete_all
|
32
|
+
# Do each delete so any on_delete and
|
33
|
+
# cascades are called, then empty the
|
34
|
+
# collection and compact the array.
|
35
|
+
bulk_update do
|
36
|
+
collection.each{|item| item.delete}
|
37
|
+
end
|
38
|
+
@collection = []
|
39
|
+
@_next_id = 1
|
40
|
+
end
|
41
|
+
|
42
|
+
# Finds row(s) within the data store. E.g.,
|
43
|
+
#
|
44
|
+
# @post = Post.find(1) # find a specific row by ID
|
45
|
+
#
|
46
|
+
# or...
|
47
|
+
#
|
48
|
+
# @posts = Post.find(:author).eq('bob').all
|
49
|
+
def find(*args, &block)
|
50
|
+
if block_given?
|
51
|
+
matches = collection.collect do |item|
|
52
|
+
item if yield(item)
|
53
|
+
end.compact
|
54
|
+
return ArrayFinderQuery.new(matches)
|
55
|
+
end
|
56
|
+
|
57
|
+
unless args[0].is_a?(Symbol) || args[0].is_a?(String)
|
58
|
+
target_id = args[0].to_i
|
59
|
+
return collection.select{|element| element.id == target_id}.first
|
60
|
+
end
|
61
|
+
|
62
|
+
ArrayFinderQuery.new(args[0].to_sym, @collection)
|
63
|
+
end
|
64
|
+
alias_method :where, :find
|
65
|
+
|
66
|
+
# Returns query result as an array
|
67
|
+
def all
|
68
|
+
collection
|
69
|
+
end
|
70
|
+
|
71
|
+
def order(field_name = nil, &block)
|
72
|
+
ArrayFinderQuery.new(@collection).order(field_name, &block)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
module PrivateClassMethods
|
78
|
+
|
79
|
+
# Returns next available id
|
80
|
+
def next_id #nodoc
|
81
|
+
@_next_id
|
82
|
+
end
|
83
|
+
|
84
|
+
# Sets next available id
|
85
|
+
def next_id=(value) #nodoc
|
86
|
+
@_next_id = value
|
87
|
+
end
|
88
|
+
|
89
|
+
# Increments next available id
|
90
|
+
def increment_id #nodoc
|
91
|
+
@_next_id += 1
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
def before_initialize(options)
|
97
|
+
assign_id(options)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Undelete does pretty much as its name implies. However,
|
101
|
+
# the natural sort order is not preserved. IMPORTANT: If
|
102
|
+
# you are trying to undo a cascading delete, this will not
|
103
|
+
# work. It only undeletes the object you still own.
|
104
|
+
|
105
|
+
def undelete
|
106
|
+
collection << self
|
107
|
+
self.class.issue_notification(self, :action => 'add')
|
108
|
+
end
|
109
|
+
|
110
|
+
# Count of objects in the current collection
|
111
|
+
def length
|
112
|
+
collection.length
|
113
|
+
end
|
114
|
+
alias_method :count, :length
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def assign_id(options) #nodoc
|
119
|
+
unless options[:id]
|
120
|
+
options[:id] = self.class.next_id
|
121
|
+
else
|
122
|
+
self.class.next_id = [options[:id].to_i, self.class.next_id].max
|
123
|
+
end
|
124
|
+
self.class.increment_id
|
125
|
+
end
|
126
|
+
|
127
|
+
def collection #nodoc
|
128
|
+
self.class.instance_variable_get('@collection')
|
129
|
+
end
|
130
|
+
|
131
|
+
def do_insert
|
132
|
+
collection << self
|
133
|
+
end
|
134
|
+
|
135
|
+
def do_update
|
136
|
+
end
|
137
|
+
|
138
|
+
def do_delete
|
139
|
+
target_index = collection.index{|item| item.id == self.id}
|
140
|
+
collection.delete_at(target_index) unless target_index.nil?
|
141
|
+
self.class.issue_notification(self, :action => 'delete')
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
end
|
@@ -16,7 +16,7 @@ module MotionModel
|
|
16
16
|
def should_return(column) #nodoc
|
17
17
|
skippable = [:id]
|
18
18
|
skippable += [:created_at, :updated_at] unless @expose_auto_date_fields
|
19
|
-
!skippable.include?(column) && !relation_column?(column)
|
19
|
+
!skippable.include?(column) && !self.class.relation_column?(column)
|
20
20
|
end
|
21
21
|
|
22
22
|
def returnable_columns #nodoc
|
@@ -40,6 +40,7 @@
|
|
40
40
|
module MotionModel
|
41
41
|
class PersistFileError < Exception; end
|
42
42
|
class RelationIsNilError < Exception; end
|
43
|
+
class AdapterNotFoundError < Exception; end
|
43
44
|
|
44
45
|
module Model
|
45
46
|
def self.included(base)
|
@@ -48,7 +49,6 @@ module MotionModel
|
|
48
49
|
base.instance_variable_set("@_columns", []) # Columns in model
|
49
50
|
base.instance_variable_set("@_column_hashes", {}) # Hashes to for quick column lookup
|
50
51
|
base.instance_variable_set("@_relations", {}) # relations
|
51
|
-
base.instance_variable_set("@collection", []) # Actual data
|
52
52
|
base.instance_variable_set("@_next_id", 1) # Next assignable id
|
53
53
|
base.instance_variable_set("@_issue_notifications", true) # Next assignable id
|
54
54
|
end
|
@@ -155,6 +155,14 @@ module MotionModel
|
|
155
155
|
column_named(column).default || nil
|
156
156
|
end
|
157
157
|
|
158
|
+
def read(attrs)
|
159
|
+
new(attrs).instance_eval do
|
160
|
+
@new_record = false
|
161
|
+
@dirty = false
|
162
|
+
self
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
158
166
|
# Creates an object and saves it. E.g.:
|
159
167
|
#
|
160
168
|
# @bob = Person.create(:name => 'Bob', :hobby => 'Bird Watching')
|
@@ -166,25 +174,6 @@ module MotionModel
|
|
166
174
|
row
|
167
175
|
end
|
168
176
|
|
169
|
-
def length
|
170
|
-
@collection.length
|
171
|
-
end
|
172
|
-
alias_method :count, :length
|
173
|
-
|
174
|
-
# Deletes all rows in the model -- no hooks are called and
|
175
|
-
# deletes are not cascading so this does not affected related
|
176
|
-
# data.
|
177
|
-
def delete_all
|
178
|
-
# Do each delete so any on_delete and
|
179
|
-
# cascades are called, then empty the
|
180
|
-
# collection and compact the array.
|
181
|
-
bulk_update do
|
182
|
-
@collection.each{|item| item.delete}
|
183
|
-
end
|
184
|
-
@collection = []
|
185
|
-
@_next_id = 1
|
186
|
-
end
|
187
|
-
|
188
177
|
# Destroys all rows in the model -- before_delete and after_delete
|
189
178
|
# hooks are called and deletes are not cascading if declared with
|
190
179
|
# :delete => destroy in the has_many macro.
|
@@ -198,56 +187,23 @@ module MotionModel
|
|
198
187
|
# Note collection is not emptied, and next_id is not reset.
|
199
188
|
end
|
200
189
|
|
201
|
-
# Finds row(s) within the data store. E.g.,
|
202
|
-
#
|
203
|
-
# @post = Post.find(1) # find a specific row by ID
|
204
|
-
#
|
205
|
-
# or...
|
206
|
-
#
|
207
|
-
# @posts = Post.find(:author).eq('bob').all
|
208
|
-
def find(*args, &block)
|
209
|
-
if block_given?
|
210
|
-
matches = @collection.collect do |item|
|
211
|
-
item if yield(item)
|
212
|
-
end.compact
|
213
|
-
return FinderQuery.new(matches)
|
214
|
-
end
|
215
|
-
|
216
|
-
unless args[0].is_a?(Symbol) || args[0].is_a?(String)
|
217
|
-
target_id = args[0].to_i
|
218
|
-
return @collection.select{|element| element.id == target_id}.first
|
219
|
-
end
|
220
|
-
|
221
|
-
FinderQuery.new(args[0].to_sym, @collection)
|
222
|
-
end
|
223
|
-
alias_method :where, :find
|
224
|
-
|
225
190
|
# Retrieves first row of query
|
226
191
|
def first
|
227
|
-
|
192
|
+
all.first
|
228
193
|
end
|
229
194
|
|
230
195
|
# Retrieves last row of query
|
231
196
|
def last
|
232
|
-
|
233
|
-
end
|
234
|
-
|
235
|
-
# Returns query result as an array
|
236
|
-
def all
|
237
|
-
@collection
|
238
|
-
end
|
239
|
-
|
240
|
-
def order(field_name = nil, &block)
|
241
|
-
FinderQuery.new(@collection).order(field_name, &block)
|
197
|
+
all.last
|
242
198
|
end
|
243
199
|
|
244
200
|
def each(&block)
|
245
201
|
raise ArgumentError.new("each requires a block") unless block_given?
|
246
|
-
|
202
|
+
all.each{|item| yield item}
|
247
203
|
end
|
248
204
|
|
249
205
|
def empty?
|
250
|
-
|
206
|
+
all.empty?
|
251
207
|
end
|
252
208
|
end
|
253
209
|
|
@@ -339,19 +295,12 @@ module MotionModel
|
|
339
295
|
@_column_hashes[name.to_sym]
|
340
296
|
end
|
341
297
|
|
342
|
-
|
343
|
-
|
344
|
-
@_next_id
|
345
|
-
end
|
346
|
-
|
347
|
-
# Sets next available id
|
348
|
-
def next_id=(value) #nodoc
|
349
|
-
@_next_id = value
|
298
|
+
def relation_column?(column) #nodoc
|
299
|
+
[:belongs_to, :belongs_to_id, :has_many].include? column_named(column).type
|
350
300
|
end
|
351
301
|
|
352
|
-
|
353
|
-
|
354
|
-
@_next_id += 1
|
302
|
+
def virtual_relation_column?(column) #nodoc
|
303
|
+
[:belongs_to, :has_many].include? column_named(column).type
|
355
304
|
end
|
356
305
|
|
357
306
|
def has_relation?(col) #nodoc
|
@@ -369,12 +318,13 @@ module MotionModel
|
|
369
318
|
end
|
370
319
|
|
371
320
|
def initialize(options = {})
|
372
|
-
|
321
|
+
raise AdapterNotFoundError.new("You must specify a persistence adapter.") unless self.respond_to? :adapter
|
373
322
|
|
374
|
-
|
323
|
+
@data ||= {}
|
324
|
+
before_initialize(options)
|
375
325
|
|
376
326
|
columns.each do |col|
|
377
|
-
unless relation_column?(col) # all data columns
|
327
|
+
unless self.class.relation_column?(col) # all data columns
|
378
328
|
initialize_data_columns col, options
|
379
329
|
else
|
380
330
|
@data[col] = options[col] if column_named(col).type == :belongs_to_id
|
@@ -382,6 +332,11 @@ module MotionModel
|
|
382
332
|
end
|
383
333
|
|
384
334
|
@dirty = true
|
335
|
+
@new_record = true
|
336
|
+
end
|
337
|
+
|
338
|
+
def new_record?
|
339
|
+
@new_record
|
385
340
|
end
|
386
341
|
|
387
342
|
# Default to_i implementation returns value of id column, much as
|
@@ -405,13 +360,14 @@ module MotionModel
|
|
405
360
|
# Existing object implies update in place
|
406
361
|
action = 'add'
|
407
362
|
set_auto_date_field 'created_at'
|
408
|
-
if
|
409
|
-
|
363
|
+
if @new_record
|
364
|
+
do_insert
|
365
|
+
else
|
366
|
+
do_update
|
410
367
|
set_auto_date_field 'updated_at'
|
411
368
|
action = 'update'
|
412
|
-
else
|
413
|
-
collection << self
|
414
369
|
end
|
370
|
+
@new_record = false
|
415
371
|
@dirty = false
|
416
372
|
self.class.issue_notification(self, :action => action)
|
417
373
|
end
|
@@ -422,7 +378,6 @@ module MotionModel
|
|
422
378
|
self.send("#{field_name}=", Time.now) if self.respond_to? field_name
|
423
379
|
end
|
424
380
|
|
425
|
-
# Deletes the current object. The object can still be used.
|
426
381
|
def call_hook(hook_name, postfix)
|
427
382
|
hook = "#{hook_name}_#{postfix}"
|
428
383
|
self.send(hook, self) if respond_to? hook.to_sym
|
@@ -436,11 +391,7 @@ module MotionModel
|
|
436
391
|
end
|
437
392
|
|
438
393
|
def delete
|
439
|
-
call_hooks('delete')
|
440
|
-
target_index = collection.index{|item| item.id == self.id}
|
441
|
-
collection.delete_at(target_index) unless target_index.nil?
|
442
|
-
self.class.issue_notification(self, :action => 'delete')
|
443
|
-
end
|
394
|
+
call_hooks('delete') { do_delete }
|
444
395
|
end
|
445
396
|
|
446
397
|
# Destroys the current object. The difference between delete
|
@@ -464,22 +415,6 @@ module MotionModel
|
|
464
415
|
delete
|
465
416
|
end
|
466
417
|
|
467
|
-
# Undelete does pretty much as its name implies. However,
|
468
|
-
# the natural sort order is not preserved. IMPORTANT: If
|
469
|
-
# you are trying to undo a cascading delete, this will not
|
470
|
-
# work. It only undeletes the object you still own.
|
471
|
-
|
472
|
-
def undelete
|
473
|
-
collection << self
|
474
|
-
self.class.issue_notification(self, :action => 'add')
|
475
|
-
end
|
476
|
-
|
477
|
-
# Count of objects in the current collection
|
478
|
-
def length
|
479
|
-
collection.length
|
480
|
-
end
|
481
|
-
alias_method :count, :length
|
482
|
-
|
483
418
|
# True if the column exists, otherwise false
|
484
419
|
def column?(column_name)
|
485
420
|
self.class.column?(column_name.to_sym)
|
@@ -518,30 +453,12 @@ module MotionModel
|
|
518
453
|
@dirty
|
519
454
|
end
|
520
455
|
|
521
|
-
|
522
456
|
private
|
523
457
|
|
524
|
-
def assign_id(options) #nodoc
|
525
|
-
unless options[:id]
|
526
|
-
options[:id] = self.class.next_id
|
527
|
-
else
|
528
|
-
self.class.next_id = [options[:id].to_i, self.class.next_id].max
|
529
|
-
end
|
530
|
-
self.class.increment_id
|
531
|
-
end
|
532
|
-
|
533
|
-
def relation_column?(column) #nodoc
|
534
|
-
[:belongs_to, :belongs_to_id, :has_many].include? column_named(column).type
|
535
|
-
end
|
536
|
-
|
537
458
|
def initialize_data_columns(column, options) #nodoc
|
538
459
|
self.send("#{column}=".to_sym, options[column] || self.class.default(column))
|
539
460
|
end
|
540
461
|
|
541
|
-
def collection #nodoc
|
542
|
-
self.class.instance_variable_get('@collection')
|
543
|
-
end
|
544
|
-
|
545
462
|
def column_named(name) #nodoc
|
546
463
|
self.class.column_named(name.to_sym)
|
547
464
|
end
|
@@ -568,14 +485,5 @@ module MotionModel
|
|
568
485
|
end
|
569
486
|
end
|
570
487
|
|
571
|
-
# Any way you reach this means you've tried to access a method
|
572
|
-
# not defined on this model.
|
573
|
-
def method_missing(method, *args, &block) #nodoc
|
574
|
-
if self.respond_to? method
|
575
|
-
return method(args, &block)
|
576
|
-
else
|
577
|
-
raise NoMethodError.new("nil column #{self.class}##{method} accessed from #{caller[1]}.")
|
578
|
-
end
|
579
|
-
end
|
580
488
|
end
|
581
489
|
end
|
data/lib/motion_model/version.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
|
1
|
+
# 0.3.8 is the last version without adapters.
|
2
|
+
# for backward compatibility, users should
|
3
|
+
# specify that version in their gem command
|
4
|
+
# or forward port their code to take advantage
|
5
|
+
# of adapters.
|
2
6
|
module MotionModel
|
3
|
-
VERSION = "0.
|
7
|
+
VERSION = "0.4.0"
|
4
8
|
end
|
@@ -1,11 +1,13 @@
|
|
1
1
|
class Assignee
|
2
2
|
include MotionModel::Model
|
3
|
+
include MotionModel::ArrayModelAdapter
|
3
4
|
columns :assignee_name => :string
|
4
5
|
belongs_to :task
|
5
6
|
end
|
6
7
|
|
7
8
|
class Task
|
8
9
|
include MotionModel::Model
|
10
|
+
include MotionModel::ArrayModelAdapter
|
9
11
|
columns :name => :string,
|
10
12
|
:details => :string,
|
11
13
|
:some_day => :date
|
@@ -14,6 +16,7 @@ end
|
|
14
16
|
|
15
17
|
class CascadingTask
|
16
18
|
include MotionModel::Model
|
19
|
+
include MotionModel::ArrayModelAdapter
|
17
20
|
columns :name => :string,
|
18
21
|
:details => :string,
|
19
22
|
:some_day => :date
|
@@ -22,6 +25,7 @@ end
|
|
22
25
|
|
23
26
|
class CascadedAssignee
|
24
27
|
include MotionModel::Model
|
28
|
+
include MotionModel::ArrayModelAdapter
|
25
29
|
columns :assignee_name => :string
|
26
30
|
belongs_to :cascading_task
|
27
31
|
has_many :employees
|
@@ -29,6 +33,7 @@ end
|
|
29
33
|
|
30
34
|
class Employee
|
31
35
|
include MotionModel::Model
|
36
|
+
include MotionModel::ArrayModelAdapter
|
32
37
|
columns :name
|
33
38
|
belongs_to :CascadedAssignee
|
34
39
|
end
|
data/spec/column_options_spec.rb
CHANGED
data/spec/date_spec.rb
CHANGED
@@ -14,6 +14,7 @@ describe "time conversions" do
|
|
14
14
|
it "Sets created_at when an item is created" do
|
15
15
|
class Creatable
|
16
16
|
include MotionModel::Model
|
17
|
+
include MotionModel::ArrayModelAdapter
|
17
18
|
columns :name => :string,
|
18
19
|
:created_at => :date
|
19
20
|
end
|
@@ -25,6 +26,7 @@ describe "time conversions" do
|
|
25
26
|
it "Sets updated_at when an item is created" do
|
26
27
|
class Updateable
|
27
28
|
include MotionModel::Model
|
29
|
+
include MotionModel::ArrayModelAdapter
|
28
30
|
columns :name => :string,
|
29
31
|
:created_at => :date,
|
30
32
|
:updated_at => :date
|
data/spec/finder_spec.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
class Task
|
2
2
|
include MotionModel::Model
|
3
|
-
|
3
|
+
include MotionModel::ArrayModelAdapter
|
4
|
+
columns :name => :string,
|
4
5
|
:details => :string,
|
5
6
|
:some_day => :date
|
6
7
|
end
|
@@ -47,7 +48,7 @@ describe 'finders' do
|
|
47
48
|
end
|
48
49
|
|
49
50
|
it 'returns a FinderQuery object' do
|
50
|
-
Task.where(:details).should.is_a(MotionModel::
|
51
|
+
Task.where(:details).should.is_a(MotionModel::ArrayFinderQuery)
|
51
52
|
end
|
52
53
|
|
53
54
|
it 'using where instead of find' do
|
@@ -58,6 +59,7 @@ describe 'finders' do
|
|
58
59
|
it "performs set inclusion(in) queries" do
|
59
60
|
class InTest
|
60
61
|
include MotionModel::Model
|
62
|
+
include MotionModel::ArrayModelAdapter
|
61
63
|
columns :name
|
62
64
|
end
|
63
65
|
|
@@ -92,7 +94,7 @@ describe 'finders' do
|
|
92
94
|
end
|
93
95
|
|
94
96
|
it 'returns a FinderQuery' do
|
95
|
-
@items_less_than_5.should.is_a MotionModel::
|
97
|
+
@items_less_than_5.should.is_a MotionModel::ArrayFinderQuery
|
96
98
|
end
|
97
99
|
|
98
100
|
it 'handles block-style finders' do
|
data/spec/formotion_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
class ModelWithOptions
|
2
2
|
include MotionModel::Model
|
3
|
+
include MotionModel::ArrayModelAdapter
|
3
4
|
include MotionModel::Formotion
|
4
5
|
|
5
6
|
columns :name => :string,
|
@@ -13,6 +14,7 @@ end
|
|
13
14
|
|
14
15
|
class RelatedModel
|
15
16
|
include MotionModel::Model
|
17
|
+
include MotionModel::ArrayModelAdapter
|
16
18
|
|
17
19
|
columns :name => :string
|
18
20
|
belongs_to :model_with_options
|
data/spec/model_casting_spec.rb
CHANGED
data/spec/model_hook_spec.rb
CHANGED
data/spec/model_spec.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
class Task
|
2
2
|
include MotionModel::Model
|
3
|
-
|
3
|
+
include MotionModel::ArrayModelAdapter
|
4
|
+
columns :name => :string,
|
4
5
|
:details => :string,
|
5
6
|
:some_day => :date
|
6
7
|
|
@@ -11,11 +12,13 @@ end
|
|
11
12
|
|
12
13
|
class ATask
|
13
14
|
include MotionModel::Model
|
15
|
+
include MotionModel::ArrayModelAdapter
|
14
16
|
columns :name, :details, :some_day
|
15
17
|
end
|
16
18
|
|
17
19
|
class TypeCast
|
18
20
|
include MotionModel::Model
|
21
|
+
include MotionModel::ArrayModelAdapter
|
19
22
|
columns :a_boolean => :boolean,
|
20
23
|
:an_int => {:type => :int, :default => 3},
|
21
24
|
:an_integer => :integer,
|
@@ -230,6 +233,15 @@ describe "Creating a model" do
|
|
230
233
|
@new_task.save
|
231
234
|
lambda{@new_task.name = 'now dirty'}.should.change{@new_task.dirty?}
|
232
235
|
end
|
236
|
+
|
237
|
+
it 'marks an updated object as clean' do
|
238
|
+
@new_task.save
|
239
|
+
@new_task.should.not.be.dirty
|
240
|
+
@new_task.name = 'now updating task'
|
241
|
+
@new_task.should.be.dirty
|
242
|
+
@new_task.save
|
243
|
+
@new_task.should.not.be.dirty
|
244
|
+
end
|
233
245
|
end
|
234
246
|
end
|
235
247
|
|
data/spec/notification_spec.rb
CHANGED
data/spec/persistence_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
class PersistTask
|
2
2
|
include MotionModel::Model
|
3
|
+
include MotionModel::ArrayModelAdapter
|
3
4
|
columns :name, :desc
|
4
5
|
end
|
5
6
|
|
@@ -33,6 +34,7 @@ describe 'persistence' do
|
|
33
34
|
it 'column addition' do
|
34
35
|
class Foo
|
35
36
|
include MotionModel::Model
|
37
|
+
include MotionModel::ArrayModelAdapter
|
36
38
|
columns :name => :string
|
37
39
|
end
|
38
40
|
@foo = Foo.create(:name=> 'Bob')
|
@@ -42,6 +44,7 @@ describe 'persistence' do
|
|
42
44
|
|
43
45
|
class Foo
|
44
46
|
include MotionModel::Model
|
47
|
+
include MotionModel::ArrayModelAdapter
|
45
48
|
columns :name => :string,
|
46
49
|
:address => :string
|
47
50
|
end
|
@@ -58,6 +61,7 @@ describe 'persistence' do
|
|
58
61
|
it "column removal" do
|
59
62
|
class Foo
|
60
63
|
include MotionModel::Model
|
64
|
+
include MotionModel::ArrayModelAdapter
|
61
65
|
columns :name => :string, :desc => :string
|
62
66
|
end
|
63
67
|
|
@@ -69,6 +73,7 @@ describe 'persistence' do
|
|
69
73
|
Object.send(:remove_const, :Foo)
|
70
74
|
class Foo
|
71
75
|
include MotionModel::Model
|
76
|
+
include MotionModel::ArrayModelAdapter
|
72
77
|
columns :name => :string,
|
73
78
|
:address => :string
|
74
79
|
end
|
@@ -86,6 +91,7 @@ describe 'persistence' do
|
|
86
91
|
describe "remembering filename" do
|
87
92
|
class Foo
|
88
93
|
include MotionModel::Model
|
94
|
+
include MotionModel::ArrayModelAdapter
|
89
95
|
columns :name => :string
|
90
96
|
end
|
91
97
|
|
@@ -142,12 +148,14 @@ end
|
|
142
148
|
|
143
149
|
class Parent
|
144
150
|
include MotionModel::Model
|
151
|
+
include MotionModel::ArrayModelAdapter
|
145
152
|
columns :name
|
146
153
|
has_many :children
|
147
154
|
end
|
148
155
|
|
149
156
|
class Child
|
150
157
|
include MotionModel::Model
|
158
|
+
include MotionModel::ArrayModelAdapter
|
151
159
|
columns :name
|
152
160
|
belongs_to :parent
|
153
161
|
end
|
data/spec/relation_spec.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
class Assignee
|
2
2
|
include MotionModel::Model
|
3
|
+
include MotionModel::ArrayModelAdapter
|
3
4
|
columns :assignee_name => :string
|
4
5
|
belongs_to :task
|
5
6
|
end
|
6
7
|
|
7
8
|
class Task
|
8
9
|
include MotionModel::Model
|
10
|
+
include MotionModel::ArrayModelAdapter
|
9
11
|
columns :name => :string,
|
10
12
|
:details => :string,
|
11
13
|
:some_day => :date
|
@@ -15,6 +17,7 @@ end
|
|
15
17
|
|
16
18
|
class User
|
17
19
|
include MotionModel::Model
|
20
|
+
include MotionModel::ArrayModelAdapter
|
18
21
|
columns :name => :string
|
19
22
|
|
20
23
|
has_many :email_accounts
|
@@ -22,6 +25,7 @@ end
|
|
22
25
|
|
23
26
|
class EmailAccount
|
24
27
|
include MotionModel::Model
|
28
|
+
include MotionModel::ArrayModelAdapter
|
25
29
|
columns :name => :string
|
26
30
|
belongs_to :user
|
27
31
|
end
|
data/spec/transaction_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
class TransactClass
|
2
2
|
include MotionModel::Model
|
3
|
+
include MotionModel::ArrayModelAdapter
|
3
4
|
include MotionModel::Model::Transactions
|
4
5
|
columns :name, :age
|
5
6
|
has_many :transaction_things
|
@@ -7,6 +8,7 @@ end
|
|
7
8
|
|
8
9
|
class TransactionThing
|
9
10
|
include MotionModel::Model
|
11
|
+
include MotionModel::ArrayModelAdapter
|
10
12
|
include MotionModel::Model::Transactions
|
11
13
|
columns :thingie_description
|
12
14
|
belongs_to :transact_class
|
data/spec/validation_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
class ValidatableTask
|
2
2
|
include MotionModel::Model
|
3
|
+
include MotionModel::ArrayModelAdapter
|
3
4
|
include MotionModel::Validatable
|
4
5
|
columns :name => :string,
|
5
6
|
:email => :string,
|
@@ -137,6 +138,7 @@ end
|
|
137
138
|
|
138
139
|
class VTask
|
139
140
|
include MotionModel::Model
|
141
|
+
include MotionModel::ArrayModelAdapter
|
140
142
|
include MotionModel::Validatable
|
141
143
|
|
142
144
|
columns :name => :string
|
@@ -167,4 +169,4 @@ describe "saving with validations" do
|
|
167
169
|
lambda { task.save }.should.change { VTask.count }
|
168
170
|
end
|
169
171
|
|
170
|
-
end
|
172
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: motion_model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-02-
|
12
|
+
date: 2013-02-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bubble-wrap
|
@@ -41,10 +41,11 @@ files:
|
|
41
41
|
- Rakefile
|
42
42
|
- app/app_delegate.rb
|
43
43
|
- lib/motion_model.rb
|
44
|
+
- lib/motion_model/adapters/array_model_adapter.rb
|
44
45
|
- lib/motion_model/ext.rb
|
45
46
|
- lib/motion_model/input_helpers.rb
|
47
|
+
- lib/motion_model/model/array_finder_query.rb
|
46
48
|
- lib/motion_model/model/column.rb
|
47
|
-
- lib/motion_model/model/finder_query.rb
|
48
49
|
- lib/motion_model/model/formotion.rb
|
49
50
|
- lib/motion_model/model/model.rb
|
50
51
|
- lib/motion_model/model/model_casts.rb
|