couchrest_model 1.1.0.beta3 → 1.1.0.beta4
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/VERSION +1 -1
- data/couchrest_model.gemspec +1 -1
- data/history.txt +5 -1
- data/lib/couchrest/model/base.rb +1 -9
- data/lib/couchrest/model/casted_array.rb +26 -23
- data/lib/couchrest/model/casted_by.rb +12 -2
- data/lib/couchrest/model/casted_hash.rb +9 -1
- data/lib/couchrest/model/casted_model.rb +10 -11
- data/lib/couchrest/model/dirty.rb +3 -13
- data/lib/couchrest/model/persistence.rb +4 -10
- data/lib/couchrest/model/properties.rb +11 -26
- data/lib/couchrest/model/property.rb +4 -6
- data/spec/couchrest/casted_model_spec.rb +8 -0
- data/spec/couchrest/dirty_spec.rb +45 -10
- data/spec/couchrest/persistence_spec.rb +1 -1
- metadata +14 -4
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.1.0.
|
|
1
|
+
1.1.0.beta4
|
data/couchrest_model.gemspec
CHANGED
|
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
|
|
|
25
25
|
|
|
26
26
|
s.add_dependency(%q<couchrest>, "1.1.0.pre2")
|
|
27
27
|
s.add_dependency(%q<mime-types>, "~> 1.15")
|
|
28
|
-
s.add_dependency(%q<activemodel>, "~> 3.0.
|
|
28
|
+
s.add_dependency(%q<activemodel>, "~> 3.0.5")
|
|
29
29
|
s.add_dependency(%q<tzinfo>, "~> 0.3.22")
|
|
30
30
|
s.add_dependency(%q<railties>, "~> 3.0.0")
|
|
31
31
|
s.add_development_dependency(%q<rspec>, ">= 2.0.0")
|
data/history.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
== 1.1.0.
|
|
1
|
+
== 1.1.0.beta4
|
|
2
2
|
|
|
3
3
|
* Major changes:
|
|
4
4
|
* Fast Dirty Tracking! Many thanks to @sobakasu (Andrew Williams)
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
* Added "auto_update_design_doc" configuration option.
|
|
11
11
|
* Using #descending on View object will automatically swap startkey with endkey.
|
|
12
12
|
|
|
13
|
+
== 1.1.0.beta3
|
|
14
|
+
|
|
15
|
+
* Removed
|
|
16
|
+
|
|
13
17
|
== 1.1.0.beta2
|
|
14
18
|
|
|
15
19
|
* Minor enhancements:
|
data/lib/couchrest/model/base.rb
CHANGED
|
@@ -18,8 +18,8 @@ module CouchRest
|
|
|
18
18
|
include CouchRest::Model::Associations
|
|
19
19
|
include CouchRest::Model::Validations
|
|
20
20
|
include CouchRest::Model::Designs
|
|
21
|
-
include CouchRest::Model::Dirty
|
|
22
21
|
include CouchRest::Model::CastedBy
|
|
22
|
+
include CouchRest::Model::Dirty
|
|
23
23
|
|
|
24
24
|
def self.subclasses
|
|
25
25
|
@subclasses ||= []
|
|
@@ -74,14 +74,6 @@ module CouchRest
|
|
|
74
74
|
super
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
-
### instance methods
|
|
78
|
-
|
|
79
|
-
# Checks if we're the top document
|
|
80
|
-
# (overrides base_doc? in casted_by.rb)
|
|
81
|
-
def base_doc?
|
|
82
|
-
!@casted_by
|
|
83
|
-
end
|
|
84
|
-
|
|
85
77
|
## Compatibility with ActiveSupport and older frameworks
|
|
86
78
|
|
|
87
79
|
# Hack so that CouchRest::Document, which descends from Hash,
|
|
@@ -5,25 +5,36 @@
|
|
|
5
5
|
|
|
6
6
|
module CouchRest::Model
|
|
7
7
|
class CastedArray < Array
|
|
8
|
+
include CouchRest::Model::CastedBy
|
|
8
9
|
include CouchRest::Model::Dirty
|
|
9
|
-
attr_accessor :
|
|
10
|
-
attr_accessor :property
|
|
10
|
+
attr_accessor :casted_by_property
|
|
11
11
|
|
|
12
|
-
def initialize(array, property)
|
|
13
|
-
self.
|
|
12
|
+
def initialize(array, property, parent = nil)
|
|
13
|
+
self.casted_by_property = property
|
|
14
|
+
self.casted_by = parent unless parent.nil?
|
|
14
15
|
super(array)
|
|
15
16
|
end
|
|
16
|
-
|
|
17
|
+
|
|
18
|
+
# Adding new entries
|
|
19
|
+
|
|
17
20
|
def << obj
|
|
18
|
-
couchrest_parent_will_change! if use_dirty?
|
|
19
21
|
super(instantiate_and_cast(obj))
|
|
20
22
|
end
|
|
21
|
-
|
|
23
|
+
|
|
22
24
|
def push(obj)
|
|
23
|
-
couchrest_parent_will_change! if use_dirty?
|
|
24
25
|
super(instantiate_and_cast(obj))
|
|
25
26
|
end
|
|
26
27
|
|
|
28
|
+
def unshift(obj)
|
|
29
|
+
super(instantiate_and_cast(obj))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def []= index, obj
|
|
33
|
+
value = instantiate_and_cast(obj, false)
|
|
34
|
+
couchrest_parent_will_change! if use_dirty? && value != self[index]
|
|
35
|
+
super(index, value)
|
|
36
|
+
end
|
|
37
|
+
|
|
27
38
|
def pop
|
|
28
39
|
couchrest_parent_will_change! if use_dirty? && self.length > 0
|
|
29
40
|
super
|
|
@@ -34,17 +45,6 @@ module CouchRest::Model
|
|
|
34
45
|
super
|
|
35
46
|
end
|
|
36
47
|
|
|
37
|
-
def unshift(obj)
|
|
38
|
-
couchrest_parent_will_change! if use_dirty?
|
|
39
|
-
super(instantiate_and_cast(obj))
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def []= index, obj
|
|
43
|
-
value = instantiate_and_cast(obj)
|
|
44
|
-
couchrest_parent_will_change! if use_dirty? && value != self[index]
|
|
45
|
-
super(index, value)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
48
|
def clear
|
|
49
49
|
couchrest_parent_will_change! if use_dirty? && self.length > 0
|
|
50
50
|
super
|
|
@@ -52,11 +52,14 @@ module CouchRest::Model
|
|
|
52
52
|
|
|
53
53
|
protected
|
|
54
54
|
|
|
55
|
-
def instantiate_and_cast(obj)
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
def instantiate_and_cast(obj, change = true)
|
|
56
|
+
property = casted_by_property
|
|
57
|
+
couchrest_parent_will_change! if change && use_dirty?
|
|
58
|
+
if casted_by && property && obj.class != property.type_class
|
|
59
|
+
property.cast_value(casted_by, obj)
|
|
58
60
|
else
|
|
59
|
-
obj.casted_by =
|
|
61
|
+
obj.casted_by = casted_by if obj.respond_to?(:casted_by)
|
|
62
|
+
obj.casted_by_property = casted_by_property if obj.respond_to?(:casted_by_property)
|
|
60
63
|
obj
|
|
61
64
|
end
|
|
62
65
|
end
|
|
@@ -4,6 +4,7 @@ module CouchRest::Model
|
|
|
4
4
|
extend ActiveSupport::Concern
|
|
5
5
|
included do
|
|
6
6
|
self.send(:attr_accessor, :casted_by)
|
|
7
|
+
self.send(:attr_accessor, :casted_by_property)
|
|
7
8
|
end
|
|
8
9
|
|
|
9
10
|
# Gets a reference to the actual document in the DB
|
|
@@ -11,13 +12,22 @@ module CouchRest::Model
|
|
|
11
12
|
# Otherwise we're at the top and we return self
|
|
12
13
|
def base_doc
|
|
13
14
|
return self if base_doc?
|
|
14
|
-
|
|
15
|
+
casted_by ? casted_by.base_doc : nil
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
# Checks if we're the top document
|
|
18
19
|
def base_doc?
|
|
19
|
-
|
|
20
|
+
!casted_by
|
|
20
21
|
end
|
|
21
22
|
|
|
23
|
+
# Provide the property this casted model instance has been
|
|
24
|
+
# used by. If it has not been set, search through the
|
|
25
|
+
# casted_by objects properties to try and find it.
|
|
26
|
+
#def casted_by_property
|
|
27
|
+
# return nil unless casted_by
|
|
28
|
+
# attrs = casted_by.attributes
|
|
29
|
+
# @casted_by_property ||= casted_by.properties.detect{ |k| attrs[k.to_s] === self }
|
|
30
|
+
#end
|
|
31
|
+
|
|
22
32
|
end
|
|
23
33
|
end
|
|
@@ -3,8 +3,16 @@
|
|
|
3
3
|
|
|
4
4
|
module CouchRest::Model
|
|
5
5
|
class CastedHash < Hash
|
|
6
|
+
include CouchRest::Model::CastedBy
|
|
6
7
|
include CouchRest::Model::Dirty
|
|
7
|
-
attr_accessor :
|
|
8
|
+
attr_accessor :casted_by_property
|
|
9
|
+
|
|
10
|
+
def self.[](hash, property, parent = nil)
|
|
11
|
+
obj = super(hash)
|
|
12
|
+
obj.casted_by_property = property
|
|
13
|
+
obj.casted_by = parent unless parent.nil?
|
|
14
|
+
obj
|
|
15
|
+
end
|
|
8
16
|
|
|
9
17
|
# needed for dirty
|
|
10
18
|
def attributes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module CouchRest::Model
|
|
2
2
|
module CastedModel
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
extend ActiveSupport::Concern
|
|
5
5
|
|
|
6
6
|
included do
|
|
@@ -10,8 +10,14 @@ module CouchRest::Model
|
|
|
10
10
|
include CouchRest::Model::PropertyProtection
|
|
11
11
|
include CouchRest::Model::Associations
|
|
12
12
|
include CouchRest::Model::Validations
|
|
13
|
+
include CouchRest::Model::CastedBy
|
|
13
14
|
include CouchRest::Model::Dirty
|
|
14
|
-
|
|
15
|
+
class_eval do
|
|
16
|
+
# Override CastedBy's base_doc?
|
|
17
|
+
def base_doc?
|
|
18
|
+
false # Can never be base doc!
|
|
19
|
+
end
|
|
20
|
+
end
|
|
15
21
|
end
|
|
16
22
|
|
|
17
23
|
def initialize(keys = {})
|
|
@@ -21,7 +27,6 @@ module CouchRest::Model
|
|
|
21
27
|
end
|
|
22
28
|
|
|
23
29
|
def []= key, value
|
|
24
|
-
couchrest_attribute_will_change!(key) if self[key] != value
|
|
25
30
|
super(key.to_s, value)
|
|
26
31
|
end
|
|
27
32
|
|
|
@@ -29,17 +34,10 @@ module CouchRest::Model
|
|
|
29
34
|
super(key.to_s)
|
|
30
35
|
end
|
|
31
36
|
|
|
32
|
-
# Gets a reference to the top level extended
|
|
33
|
-
# document that a model is saved inside of
|
|
34
|
-
def base_doc
|
|
35
|
-
return nil unless @casted_by
|
|
36
|
-
@casted_by.base_doc
|
|
37
|
-
end
|
|
38
|
-
|
|
39
37
|
# False if the casted model has already
|
|
40
38
|
# been saved in the containing document
|
|
41
39
|
def new?
|
|
42
|
-
|
|
40
|
+
casted_by.nil? ? true : casted_by.new?
|
|
43
41
|
end
|
|
44
42
|
alias :new_record? :new?
|
|
45
43
|
|
|
@@ -68,4 +66,5 @@ module CouchRest::Model
|
|
|
68
66
|
alias :attributes= :update_attributes_without_saving
|
|
69
67
|
|
|
70
68
|
end
|
|
69
|
+
|
|
71
70
|
end
|
|
@@ -10,7 +10,6 @@ module CouchRest
|
|
|
10
10
|
# This applies to both Model::Base and Model::CastedModel
|
|
11
11
|
module Dirty
|
|
12
12
|
extend ActiveSupport::Concern
|
|
13
|
-
include CouchRest::Model::CastedBy # needed for base_doc
|
|
14
13
|
include ActiveModel::Dirty
|
|
15
14
|
|
|
16
15
|
included do
|
|
@@ -21,8 +20,8 @@ module CouchRest
|
|
|
21
20
|
end
|
|
22
21
|
|
|
23
22
|
def use_dirty?
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
doc = base_doc
|
|
24
|
+
doc && !doc.disable_dirty
|
|
26
25
|
end
|
|
27
26
|
|
|
28
27
|
def couchrest_attribute_will_change!(attr)
|
|
@@ -32,16 +31,7 @@ module CouchRest
|
|
|
32
31
|
end
|
|
33
32
|
|
|
34
33
|
def couchrest_parent_will_change!
|
|
35
|
-
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
private
|
|
39
|
-
|
|
40
|
-
# return the attribute name this object is referenced by in the parent
|
|
41
|
-
def casted_by_attribute
|
|
42
|
-
return @casted_by_attribute if @casted_by_attribute
|
|
43
|
-
attr = @casted_by.attributes
|
|
44
|
-
@casted_by_attribute = attr.keys.detect { |k| attr[k] == self }
|
|
34
|
+
casted_by.couchrest_attribute_will_change!(casted_by_property.name) if casted_by_property
|
|
45
35
|
end
|
|
46
36
|
|
|
47
37
|
end
|
|
@@ -30,7 +30,7 @@ module CouchRest
|
|
|
30
30
|
def update(options = {})
|
|
31
31
|
raise "Calling #{self.class.name}#update on document that has not been created!" if self.new?
|
|
32
32
|
return false unless perform_validations(options)
|
|
33
|
-
return true if !self.changed?
|
|
33
|
+
return true if !self.disable_dirty && !self.changed?
|
|
34
34
|
_run_update_callbacks do
|
|
35
35
|
_run_save_callbacks do
|
|
36
36
|
result = database.save_doc(self)
|
|
@@ -143,20 +143,14 @@ module CouchRest
|
|
|
143
143
|
# must be globally unique across all document types which share a
|
|
144
144
|
# database, so if you'd like to scope uniqueness to this class, you
|
|
145
145
|
# should use the class name as part of the unique id.
|
|
146
|
-
def unique_id
|
|
146
|
+
def unique_id(method = nil, &block)
|
|
147
147
|
if method
|
|
148
|
-
define_method :get_unique_id do
|
|
149
|
-
self.send(method)
|
|
150
|
-
end
|
|
151
148
|
define_method :set_unique_id do
|
|
152
|
-
self['_id'] ||=
|
|
149
|
+
self['_id'] ||= self.send(method)
|
|
153
150
|
end
|
|
154
151
|
elsif block
|
|
155
|
-
define_method :get_unique_id do
|
|
156
|
-
block.call(self)
|
|
157
|
-
end
|
|
158
152
|
define_method :set_unique_id do
|
|
159
|
-
uniqid =
|
|
153
|
+
uniqid = block.call(self)
|
|
160
154
|
raise ArgumentError, "unique_id block must not return nil" if uniqid.nil?
|
|
161
155
|
self['_id'] ||= uniqid
|
|
162
156
|
end
|
|
@@ -6,9 +6,9 @@ module CouchRest
|
|
|
6
6
|
|
|
7
7
|
included do
|
|
8
8
|
extlib_inheritable_accessor(:properties) unless self.respond_to?(:properties)
|
|
9
|
-
extlib_inheritable_accessor(:
|
|
9
|
+
extlib_inheritable_accessor(:properties_by_name) unless self.respond_to?(:properties_by_name)
|
|
10
10
|
self.properties ||= []
|
|
11
|
-
self.
|
|
11
|
+
self.properties_by_name ||= {}
|
|
12
12
|
raise "You can only mixin Properties in a class responding to [] and []=, if you tried to mixin CastedModel, make sure your class inherits from Hash or responds to the proper methods" unless (method_defined?(:[]) && method_defined?(:[]=))
|
|
13
13
|
end
|
|
14
14
|
|
|
@@ -20,6 +20,12 @@ module CouchRest
|
|
|
20
20
|
self.class.properties
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
# Returns all the class's properties as a Hash where the key is the name
|
|
24
|
+
# of the property.
|
|
25
|
+
def properties_by_name
|
|
26
|
+
self.class.properties_by_name
|
|
27
|
+
end
|
|
28
|
+
|
|
23
29
|
# Returns the Class properties with their values
|
|
24
30
|
#
|
|
25
31
|
# ==== Returns
|
|
@@ -43,31 +49,10 @@ module CouchRest
|
|
|
43
49
|
def write_attribute(property, value)
|
|
44
50
|
prop = find_property!(property)
|
|
45
51
|
value = prop.is_a?(String) ? value : prop.cast(self, value)
|
|
46
|
-
|
|
52
|
+
couchrest_attribute_will_change!(prop.name) if use_dirty? && self[prop.name] != value
|
|
47
53
|
self[prop.name] = value
|
|
48
54
|
end
|
|
49
55
|
|
|
50
|
-
def []=(key,value)
|
|
51
|
-
return super(key,value) unless use_dirty?
|
|
52
|
-
|
|
53
|
-
has_changes = self.changed?
|
|
54
|
-
if !has_changes && self.respond_to?(:get_unique_id)
|
|
55
|
-
check_id_change = true
|
|
56
|
-
old_id = get_unique_id
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
ret = super(key, value)
|
|
60
|
-
|
|
61
|
-
if check_id_change
|
|
62
|
-
# if we have set an attribute that results in the _id changing (unique_id),
|
|
63
|
-
# force changed? to return true so that the record can be saved
|
|
64
|
-
new_id = get_unique_id
|
|
65
|
-
changed_attributes["_id"] = new_id if old_id != new_id
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
ret
|
|
69
|
-
end
|
|
70
|
-
|
|
71
56
|
# Takes a hash as argument, and applies the values by using writer methods
|
|
72
57
|
# for each key. It doesn't save the document at the end. Raises a NoMethodError if the corresponding methods are
|
|
73
58
|
# missing. In case of error, no attributes are changed.
|
|
@@ -90,7 +75,7 @@ module CouchRest
|
|
|
90
75
|
protected
|
|
91
76
|
|
|
92
77
|
def find_property(property)
|
|
93
|
-
property.is_a?(Property) ? property : self.class.
|
|
78
|
+
property.is_a?(Property) ? property : self.class.properties_by_name[property.to_s]
|
|
94
79
|
end
|
|
95
80
|
|
|
96
81
|
# The following methods should be accessable by the Model::Base Class, but not by anything else!
|
|
@@ -212,7 +197,7 @@ module CouchRest
|
|
|
212
197
|
validates_casted_model property.name
|
|
213
198
|
end
|
|
214
199
|
properties << property
|
|
215
|
-
|
|
200
|
+
properties_by_name[property.to_s] = property
|
|
216
201
|
property
|
|
217
202
|
end
|
|
218
203
|
|
|
@@ -38,16 +38,13 @@ module CouchRest::Model
|
|
|
38
38
|
end
|
|
39
39
|
arr = value.collect { |data| cast_value(parent, data) }
|
|
40
40
|
# allow casted_by calls to be passed up chain by wrapping in CastedArray
|
|
41
|
-
|
|
42
|
-
value.casted_by = parent
|
|
41
|
+
CastedArray.new(arr, self, parent)
|
|
43
42
|
elsif (type == Object || type == Hash) && (value.class == Hash)
|
|
44
43
|
# allow casted_by calls to be passed up chain by wrapping in CastedHash
|
|
45
|
-
value
|
|
46
|
-
value.casted_by = parent
|
|
44
|
+
CastedHash[value, self, parent]
|
|
47
45
|
elsif !value.nil?
|
|
48
|
-
|
|
46
|
+
cast_value(parent, value)
|
|
49
47
|
end
|
|
50
|
-
value
|
|
51
48
|
end
|
|
52
49
|
|
|
53
50
|
# Cast an individual value, not an array
|
|
@@ -71,6 +68,7 @@ module CouchRest::Model
|
|
|
71
68
|
|
|
72
69
|
def associate_casted_value_to_parent(parent, value)
|
|
73
70
|
value.casted_by = parent if value.respond_to?(:casted_by)
|
|
71
|
+
value.casted_by_property = self if value.respond_to?(:casted_by_property)
|
|
74
72
|
value
|
|
75
73
|
end
|
|
76
74
|
|
|
@@ -79,6 +79,10 @@ describe CouchRest::Model::CastedModel do
|
|
|
79
79
|
@obj.name.should == 'Eric'
|
|
80
80
|
@obj.details['color'].should == 'orange'
|
|
81
81
|
end
|
|
82
|
+
it "should always return base_doc? as false" do
|
|
83
|
+
@obj.base_doc?.should be_false
|
|
84
|
+
end
|
|
85
|
+
|
|
82
86
|
end
|
|
83
87
|
|
|
84
88
|
describe "casted as an attribute, but without a value" do
|
|
@@ -132,6 +136,10 @@ describe CouchRest::Model::CastedModel do
|
|
|
132
136
|
@casted_obj.casted_by.should == @obj
|
|
133
137
|
end
|
|
134
138
|
|
|
139
|
+
it "should know which property casted it" do
|
|
140
|
+
@casted_obj.casted_by_property.should == @obj.properties.detect{|p| p.to_s == 'casted_attribute'}
|
|
141
|
+
end
|
|
142
|
+
|
|
135
143
|
it "should return nil for the 'no_value' attribute" do
|
|
136
144
|
@casted_obj.no_value.should be_nil
|
|
137
145
|
end
|
|
@@ -13,7 +13,7 @@ class WithCastedModelMixin < Hash
|
|
|
13
13
|
property :casted_attribute, WithCastedModelMixin
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
class
|
|
16
|
+
class DirtyModel < CouchRest::Model::Base
|
|
17
17
|
use_database DB
|
|
18
18
|
|
|
19
19
|
property :casted_attribute, WithCastedModelMixin
|
|
@@ -25,6 +25,16 @@ class DummyModel < CouchRest::Model::Base
|
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
class DirtyUniqueIdModel < CouchRest::Model::Base
|
|
29
|
+
use_database DB
|
|
30
|
+
attr_accessor :code
|
|
31
|
+
unique_id :code
|
|
32
|
+
property :title, String, :default => "Sample Title"
|
|
33
|
+
timestamps!
|
|
34
|
+
|
|
35
|
+
def code; self['_id'] || @code; end
|
|
36
|
+
end
|
|
37
|
+
|
|
28
38
|
describe "Dirty" do
|
|
29
39
|
|
|
30
40
|
describe "changes" do
|
|
@@ -66,18 +76,21 @@ describe "Dirty" do
|
|
|
66
76
|
end
|
|
67
77
|
|
|
68
78
|
it "should report no changes on a hash property with a default value" do
|
|
69
|
-
@obj =
|
|
79
|
+
@obj = DirtyModel.new
|
|
70
80
|
@obj.details.changed?.should be_false
|
|
71
81
|
end
|
|
72
82
|
|
|
73
|
-
=begin
|
|
74
83
|
# match activerecord behaviour
|
|
75
|
-
# not currently working - not too important
|
|
76
84
|
it "should report changes on a new object with attributes set" do
|
|
77
85
|
@card = Card.new(:first_name => "matt")
|
|
78
86
|
@card.changed?.should be_true
|
|
79
87
|
end
|
|
80
|
-
|
|
88
|
+
|
|
89
|
+
it "should report no changes on new object with 'unique_id' set" do
|
|
90
|
+
@obj = DirtyUniqueIdModel.new
|
|
91
|
+
@obj.changed?.should be_false
|
|
92
|
+
@obj.changes.should be_empty
|
|
93
|
+
end
|
|
81
94
|
|
|
82
95
|
it "should report no changes on objects fetched from the database" do
|
|
83
96
|
card_id = Card.create!(:first_name => "matt").id
|
|
@@ -156,15 +169,37 @@ describe "Dirty" do
|
|
|
156
169
|
it "should report changes to casted models" do
|
|
157
170
|
@cat = Cat.create!(:name => "Felix", :favorite_toy => { :name => "Mouse" })
|
|
158
171
|
@cat = Cat.find(@cat.id)
|
|
159
|
-
@cat.favorite_toy
|
|
172
|
+
@cat.favorite_toy.name = 'Feather'
|
|
160
173
|
@cat.changed?.should be_true
|
|
161
174
|
end
|
|
162
175
|
|
|
176
|
+
it "should report changes to casted model in array" do
|
|
177
|
+
@obj = Cat.create!(:name => 'felix', :toys => [{:name => "Catnip"}])
|
|
178
|
+
@obj = Cat.get(@obj.id)
|
|
179
|
+
@obj.toys.first.name.should eql('Catnip')
|
|
180
|
+
@obj.toys.first.changed?.should be_false
|
|
181
|
+
@obj.changed?.should be_false
|
|
182
|
+
@obj.toys.first.name = "Super Catnip"
|
|
183
|
+
@obj.toys.first.changed?.should be_true
|
|
184
|
+
@obj.changed?.should be_true
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
it "should report changes to anonymous casted models in array" do
|
|
188
|
+
@obj = DirtyModel.create!(:sub_models => [{:title => "Sample"}])
|
|
189
|
+
@obj = DirtyModel.get(@obj.id)
|
|
190
|
+
@obj.sub_models.first.title.should eql("Sample")
|
|
191
|
+
@obj.sub_models.first.changed?.should be_false
|
|
192
|
+
@obj.changed?.should be_false
|
|
193
|
+
@obj.sub_models.first.title = "Another Sample"
|
|
194
|
+
@obj.sub_models.first.changed?.should be_true
|
|
195
|
+
@obj.changed?.should be_true
|
|
196
|
+
end
|
|
197
|
+
|
|
163
198
|
# casted arrays
|
|
164
199
|
|
|
165
200
|
def test_casted_array(change_expected)
|
|
166
|
-
obj =
|
|
167
|
-
obj =
|
|
201
|
+
obj = DirtyModel.create!
|
|
202
|
+
obj = DirtyModel.get(obj.id)
|
|
168
203
|
array = obj.keywords
|
|
169
204
|
yield array, obj
|
|
170
205
|
if change_expected
|
|
@@ -249,8 +284,8 @@ describe "Dirty" do
|
|
|
249
284
|
# Object, {} (casted hash)
|
|
250
285
|
|
|
251
286
|
def test_casted_hash(change_expected)
|
|
252
|
-
obj =
|
|
253
|
-
obj =
|
|
287
|
+
obj = DirtyModel.create!
|
|
288
|
+
obj = DirtyModel.get(obj.id)
|
|
254
289
|
hash = obj.details
|
|
255
290
|
yield hash, obj
|
|
256
291
|
if change_expected
|
|
@@ -227,7 +227,7 @@ describe "Model Persistence" do
|
|
|
227
227
|
@templated['important-field'] = 'not-important'
|
|
228
228
|
@templated.save.should be_true
|
|
229
229
|
t = WithTemplateAndUniqueID.get('very-important')
|
|
230
|
-
t.should == @templated
|
|
230
|
+
t.id.should == @templated.id
|
|
231
231
|
end
|
|
232
232
|
|
|
233
233
|
it "should raise an error when the id is taken" do
|
metadata
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: couchrest_model
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
+
hash: -1848230064
|
|
4
5
|
prerelease: true
|
|
5
6
|
segments:
|
|
6
7
|
- 1
|
|
7
8
|
- 1
|
|
8
9
|
- 0
|
|
9
|
-
-
|
|
10
|
-
version: 1.1.0.
|
|
10
|
+
- beta4
|
|
11
|
+
version: 1.1.0.beta4
|
|
11
12
|
platform: ruby
|
|
12
13
|
authors:
|
|
13
14
|
- J. Chris Anderson
|
|
@@ -30,6 +31,7 @@ dependencies:
|
|
|
30
31
|
requirements:
|
|
31
32
|
- - "="
|
|
32
33
|
- !ruby/object:Gem::Version
|
|
34
|
+
hash: -1876988167
|
|
33
35
|
segments:
|
|
34
36
|
- 1
|
|
35
37
|
- 1
|
|
@@ -46,6 +48,7 @@ dependencies:
|
|
|
46
48
|
requirements:
|
|
47
49
|
- - ~>
|
|
48
50
|
- !ruby/object:Gem::Version
|
|
51
|
+
hash: 17
|
|
49
52
|
segments:
|
|
50
53
|
- 1
|
|
51
54
|
- 15
|
|
@@ -60,11 +63,12 @@ dependencies:
|
|
|
60
63
|
requirements:
|
|
61
64
|
- - ~>
|
|
62
65
|
- !ruby/object:Gem::Version
|
|
66
|
+
hash: 13
|
|
63
67
|
segments:
|
|
64
68
|
- 3
|
|
65
69
|
- 0
|
|
66
|
-
-
|
|
67
|
-
version: 3.0.
|
|
70
|
+
- 5
|
|
71
|
+
version: 3.0.5
|
|
68
72
|
type: :runtime
|
|
69
73
|
version_requirements: *id003
|
|
70
74
|
- !ruby/object:Gem::Dependency
|
|
@@ -75,6 +79,7 @@ dependencies:
|
|
|
75
79
|
requirements:
|
|
76
80
|
- - ~>
|
|
77
81
|
- !ruby/object:Gem::Version
|
|
82
|
+
hash: 63
|
|
78
83
|
segments:
|
|
79
84
|
- 0
|
|
80
85
|
- 3
|
|
@@ -90,6 +95,7 @@ dependencies:
|
|
|
90
95
|
requirements:
|
|
91
96
|
- - ~>
|
|
92
97
|
- !ruby/object:Gem::Version
|
|
98
|
+
hash: 7
|
|
93
99
|
segments:
|
|
94
100
|
- 3
|
|
95
101
|
- 0
|
|
@@ -105,6 +111,7 @@ dependencies:
|
|
|
105
111
|
requirements:
|
|
106
112
|
- - ">="
|
|
107
113
|
- !ruby/object:Gem::Version
|
|
114
|
+
hash: 15
|
|
108
115
|
segments:
|
|
109
116
|
- 2
|
|
110
117
|
- 0
|
|
@@ -120,6 +127,7 @@ dependencies:
|
|
|
120
127
|
requirements:
|
|
121
128
|
- - ">="
|
|
122
129
|
- !ruby/object:Gem::Version
|
|
130
|
+
hash: 5
|
|
123
131
|
segments:
|
|
124
132
|
- 0
|
|
125
133
|
- 5
|
|
@@ -247,6 +255,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
247
255
|
requirements:
|
|
248
256
|
- - ">="
|
|
249
257
|
- !ruby/object:Gem::Version
|
|
258
|
+
hash: 3
|
|
250
259
|
segments:
|
|
251
260
|
- 0
|
|
252
261
|
version: "0"
|
|
@@ -255,6 +264,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
255
264
|
requirements:
|
|
256
265
|
- - ">"
|
|
257
266
|
- !ruby/object:Gem::Version
|
|
267
|
+
hash: 25
|
|
258
268
|
segments:
|
|
259
269
|
- 1
|
|
260
270
|
- 3
|