motion_model 0.3.8 → 0.4.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/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
|