mattetti-couchrest 0.33 → 0.34
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/README.md +29 -10
- data/Rakefile +1 -0
- data/THANKS.md +1 -0
- data/lib/couchrest.rb +2 -1
- data/lib/couchrest/core/database.rb +0 -18
- data/lib/couchrest/core/document.rb +3 -2
- data/lib/couchrest/mixins/callbacks.rb +187 -138
- data/lib/couchrest/mixins/collection.rb +3 -16
- data/lib/couchrest/mixins/extended_attachments.rb +1 -1
- data/lib/couchrest/mixins/properties.rb +71 -44
- data/lib/couchrest/mixins/validation.rb +18 -29
- data/lib/couchrest/more/casted_model.rb +29 -1
- data/lib/couchrest/more/extended_document.rb +56 -17
- data/lib/couchrest/more/property.rb +19 -0
- data/lib/couchrest/support/class.rb +81 -67
- data/lib/couchrest/support/rails.rb +12 -5
- data/spec/couchrest/core/database_spec.rb +2 -2
- data/spec/couchrest/more/casted_extended_doc_spec.rb +2 -4
- data/spec/couchrest/more/casted_model_spec.rb +229 -0
- data/spec/couchrest/more/extended_doc_attachment_spec.rb +2 -2
- data/spec/couchrest/more/extended_doc_spec.rb +167 -16
- data/spec/couchrest/more/extended_doc_view_spec.rb +17 -6
- data/spec/couchrest/more/property_spec.rb +71 -3
- data/spec/fixtures/more/article.rb +2 -2
- data/spec/fixtures/more/cat.rb +1 -0
- data/spec/fixtures/more/event.rb +3 -0
- data/spec/fixtures/more/person.rb +1 -0
- metadata +3 -3
@@ -1,14 +1,5 @@
|
|
1
1
|
module CouchRest
|
2
2
|
module Mixins
|
3
|
-
module PaginatedResults
|
4
|
-
def amount_pages
|
5
|
-
@amount_pages ||= 0
|
6
|
-
end
|
7
|
-
def amount_pages=(value)
|
8
|
-
@amount_pages = value
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
3
|
module Collection
|
13
4
|
|
14
5
|
def self.included(base)
|
@@ -93,8 +84,6 @@ module CouchRest
|
|
93
84
|
DEFAULT_PAGE = 1
|
94
85
|
DEFAULT_PER_PAGE = 30
|
95
86
|
|
96
|
-
attr_accessor :amount_pages
|
97
|
-
|
98
87
|
# Create a new CollectionProxy to represent the specified view. If a
|
99
88
|
# container class is specified, the proxy will create an object of the
|
100
89
|
# given type for each row that comes back from the view. If no
|
@@ -122,11 +111,8 @@ module CouchRest
|
|
122
111
|
def paginate(options = {})
|
123
112
|
page, per_page = parse_options(options)
|
124
113
|
results = @database.view(@view_name, pagination_options(page, per_page))
|
125
|
-
@amount_pages ||= (results['total_rows'].to_f / per_page.to_f).ceil
|
126
114
|
remember_where_we_left_off(results, page)
|
127
115
|
results = convert_to_container_array(results)
|
128
|
-
results.extend(PaginatedResults)
|
129
|
-
results.amount_pages = @amount_pages
|
130
116
|
results
|
131
117
|
end
|
132
118
|
|
@@ -204,8 +190,9 @@ module CouchRest
|
|
204
190
|
def pagination_options(page, per_page)
|
205
191
|
view_options = @view_options.clone
|
206
192
|
if @last_key && @last_docid && @last_page == page - 1
|
207
|
-
view_options.delete(:key)
|
208
|
-
|
193
|
+
key = view_options.delete(:key)
|
194
|
+
end_key = view_options[:endkey] || key
|
195
|
+
options = { :startkey => @last_key, :endkey => end_key, :startkey_docid => @last_docid, :limit => per_page, :skip => 1 }
|
209
196
|
else
|
210
197
|
options = { :limit => per_page, :skip => per_page * (page - 1) }
|
211
198
|
end
|
@@ -64,7 +64,7 @@ module CouchRest
|
|
64
64
|
def set_attachment_attr(args)
|
65
65
|
content_type = args[:content_type] ? args[:content_type] : get_mime_type(args[:file])
|
66
66
|
self['_attachments'][args[:name]] = {
|
67
|
-
'
|
67
|
+
'content_type' => content_type,
|
68
68
|
'data' => encode_attachment(args[:file].read)
|
69
69
|
}
|
70
70
|
end
|
@@ -27,7 +27,7 @@ module CouchRest
|
|
27
27
|
class IncludeError < StandardError; end
|
28
28
|
|
29
29
|
def self.included(base)
|
30
|
-
base.class_eval <<-EOS, __FILE__, __LINE__
|
30
|
+
base.class_eval <<-EOS, __FILE__, __LINE__ + 1
|
31
31
|
extlib_inheritable_accessor(:properties) unless self.respond_to?(:properties)
|
32
32
|
self.properties ||= []
|
33
33
|
EOS
|
@@ -36,7 +36,7 @@ module CouchRest
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def apply_defaults
|
39
|
-
return if self.respond_to?(:
|
39
|
+
return if self.respond_to?(:new?) && (new? == false)
|
40
40
|
return unless self.class.respond_to?(:properties)
|
41
41
|
return if self.class.properties.empty?
|
42
42
|
# TODO: cache the default object
|
@@ -56,50 +56,76 @@ module CouchRest
|
|
56
56
|
def cast_keys
|
57
57
|
return unless self.class.properties
|
58
58
|
self.class.properties.each do |property|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
59
|
+
cast_property(property)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def cast_property(property, assigned=false)
|
64
|
+
return unless property.casted
|
65
|
+
key = self.has_key?(property.name) ? property.name : property.name.to_sym
|
66
|
+
# Don't cast the property unless it has a value
|
67
|
+
return unless self[key]
|
68
|
+
if property.type.is_a?(Array)
|
69
|
+
klass = ::CouchRest.constantize(property.type[0])
|
70
|
+
arr = self[key].dup.collect do |value|
|
71
|
+
unless value.instance_of?(klass)
|
72
|
+
value = convert_property_value(property, klass, value)
|
71
73
|
end
|
74
|
+
associate_casted_to_parent(value, assigned)
|
75
|
+
value
|
76
|
+
end
|
77
|
+
self[key] = klass != String ? CastedArray.new(arr) : arr
|
78
|
+
self[key].casted_by = self if self[key].respond_to?(:casted_by)
|
79
|
+
else
|
80
|
+
if property.type == 'boolean'
|
81
|
+
klass = TrueClass
|
72
82
|
else
|
73
|
-
|
74
|
-
|
75
|
-
# Using custom time parsing method because Ruby's default method is toooo slow
|
76
|
-
self[key].is_a?(String) ? Time.mktime_with_offset(self[key].dup) : self[key]
|
77
|
-
# Float instances don't get initialized with #new
|
78
|
-
elsif ((property.init_method == 'new') && target == 'Float')
|
79
|
-
cast_float(self[key])
|
80
|
-
# 'boolean' type is simply used to generate a property? accessor method
|
81
|
-
elsif ((property.init_method == 'new') && target == 'boolean')
|
82
|
-
self[key]
|
83
|
-
else
|
84
|
-
# Let people use :send as a Time parse arg
|
85
|
-
klass = ::CouchRest.constantize(target)
|
86
|
-
klass.send(property.init_method, self[key].dup)
|
87
|
-
end
|
88
|
-
self[property.name].casted_by = self if self[property.name].respond_to?(:casted_by)
|
89
|
-
end
|
83
|
+
klass = ::CouchRest.constantize(property.type)
|
84
|
+
end
|
90
85
|
|
91
|
-
|
92
|
-
|
93
|
-
def cast_float(value)
|
94
|
-
begin
|
95
|
-
Float(value)
|
96
|
-
rescue
|
97
|
-
value
|
86
|
+
unless self[key].instance_of?(klass)
|
87
|
+
self[key] = convert_property_value(property, klass, self[property.name])
|
98
88
|
end
|
89
|
+
associate_casted_to_parent(self[property.name], assigned)
|
99
90
|
end
|
100
91
|
|
101
92
|
end
|
102
93
|
|
94
|
+
def associate_casted_to_parent(casted, assigned)
|
95
|
+
casted.casted_by = self if casted.respond_to?(:casted_by)
|
96
|
+
casted.document_saved = true if !assigned && casted.respond_to?(:document_saved)
|
97
|
+
end
|
98
|
+
|
99
|
+
def convert_property_value(property, klass, value)
|
100
|
+
if ((property.init_method == 'new') && klass == Time)
|
101
|
+
# Using custom time parsing method because Ruby's default method is toooo slow
|
102
|
+
value.is_a?(String) ? Time.mktime_with_offset(value.dup) : value
|
103
|
+
# Float instances don't get initialized with #new
|
104
|
+
elsif ((property.init_method == 'new') && klass == Float)
|
105
|
+
cast_float(value)
|
106
|
+
# 'boolean' type is simply used to generate a property? accessor method
|
107
|
+
elsif ((property.init_method == 'new') && klass == TrueClass)
|
108
|
+
value
|
109
|
+
else
|
110
|
+
klass.send(property.init_method, value.dup)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def cast_property_by_name(property_name)
|
115
|
+
return unless self.class.properties
|
116
|
+
property = self.class.properties.detect{|property| property.name == property_name}
|
117
|
+
return unless property
|
118
|
+
cast_property(property, true)
|
119
|
+
end
|
120
|
+
|
121
|
+
def cast_float(value)
|
122
|
+
begin
|
123
|
+
Float(value)
|
124
|
+
rescue
|
125
|
+
value
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
103
129
|
module ClassMethods
|
104
130
|
|
105
131
|
def property(name, options={})
|
@@ -125,7 +151,7 @@ module CouchRest
|
|
125
151
|
# defines the getter for the property (and optional aliases)
|
126
152
|
def create_property_getter(property)
|
127
153
|
# meth = property.name
|
128
|
-
class_eval <<-EOS, __FILE__, __LINE__
|
154
|
+
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
129
155
|
def #{property.name}
|
130
156
|
self['#{property.name}']
|
131
157
|
end
|
@@ -144,7 +170,7 @@ module CouchRest
|
|
144
170
|
end
|
145
171
|
|
146
172
|
if property.alias
|
147
|
-
class_eval <<-EOS, __FILE__, __LINE__
|
173
|
+
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
148
174
|
alias #{property.alias.to_sym} #{property.name.to_sym}
|
149
175
|
EOS
|
150
176
|
end
|
@@ -152,16 +178,17 @@ module CouchRest
|
|
152
178
|
|
153
179
|
# defines the setter for the property (and optional aliases)
|
154
180
|
def create_property_setter(property)
|
155
|
-
|
181
|
+
property_name = property.name
|
156
182
|
class_eval <<-EOS
|
157
|
-
def #{
|
158
|
-
self['#{
|
183
|
+
def #{property_name}=(value)
|
184
|
+
self['#{property_name}'] = value
|
185
|
+
cast_property_by_name('#{property_name}')
|
159
186
|
end
|
160
187
|
EOS
|
161
188
|
|
162
189
|
if property.alias
|
163
190
|
class_eval <<-EOS
|
164
|
-
alias #{property.alias.to_sym}= #{
|
191
|
+
alias #{property.alias.to_sym}= #{property_name.to_sym}=
|
165
192
|
EOS
|
166
193
|
end
|
167
194
|
end
|
@@ -50,7 +50,10 @@ module CouchRest
|
|
50
50
|
|
51
51
|
def self.included(base)
|
52
52
|
base.extlib_inheritable_accessor(:auto_validation)
|
53
|
-
base.class_eval <<-EOS, __FILE__, __LINE__
|
53
|
+
base.class_eval <<-EOS, __FILE__, __LINE__ + 1
|
54
|
+
# Callbacks
|
55
|
+
define_callbacks :validate
|
56
|
+
|
54
57
|
# Turn off auto validation by default
|
55
58
|
self.auto_validation ||= false
|
56
59
|
|
@@ -71,9 +74,10 @@ module CouchRest
|
|
71
74
|
EOS
|
72
75
|
|
73
76
|
base.extend(ClassMethods)
|
74
|
-
base.class_eval <<-EOS, __FILE__, __LINE__
|
77
|
+
base.class_eval <<-EOS, __FILE__, __LINE__ + 1
|
78
|
+
define_callbacks :validate
|
75
79
|
if method_defined?(:_run_save_callbacks)
|
76
|
-
|
80
|
+
set_callback :save, :before, :check_validations
|
77
81
|
end
|
78
82
|
EOS
|
79
83
|
base.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
@@ -115,8 +119,7 @@ module CouchRest
|
|
115
119
|
# Check if a resource is valid in a given context
|
116
120
|
#
|
117
121
|
def valid?(context = :default)
|
118
|
-
|
119
|
-
result && validate_casted_arrays
|
122
|
+
recursive_valid?(self, context, true)
|
120
123
|
end
|
121
124
|
|
122
125
|
# checking on casted objects
|
@@ -133,29 +136,24 @@ module CouchRest
|
|
133
136
|
result
|
134
137
|
end
|
135
138
|
|
136
|
-
# Begin a recursive walk of the model checking validity
|
137
|
-
#
|
138
|
-
def all_valid?(context = :default)
|
139
|
-
recursive_valid?(self, context, true)
|
140
|
-
end
|
141
|
-
|
142
139
|
# Do recursive validity checking
|
143
140
|
#
|
144
141
|
def recursive_valid?(target, context, state)
|
145
142
|
valid = state
|
146
|
-
target.
|
147
|
-
|
148
|
-
|
149
|
-
valid = valid && recursive_valid?(ivar_value, context, valid)
|
150
|
-
elsif ivar_value.respond_to?(:each)
|
151
|
-
ivar_value.each do |item|
|
143
|
+
target.each do |key, prop|
|
144
|
+
if prop.is_a?(Array)
|
145
|
+
prop.each do |item|
|
152
146
|
if item.validatable?
|
153
|
-
valid =
|
147
|
+
valid = recursive_valid?(item, context, valid) && valid
|
154
148
|
end
|
155
149
|
end
|
150
|
+
elsif prop.validatable?
|
151
|
+
valid = recursive_valid?(prop, context, valid) && valid
|
156
152
|
end
|
157
153
|
end
|
158
|
-
|
154
|
+
target._run_validate_callbacks do
|
155
|
+
target.class.validators.execute(context, target) && valid
|
156
|
+
end
|
159
157
|
end
|
160
158
|
|
161
159
|
|
@@ -212,21 +210,12 @@ module CouchRest
|
|
212
210
|
def create_context_instance_methods(context)
|
213
211
|
name = "valid_for_#{context.to_s}?" # valid_for_signup?
|
214
212
|
if !self.instance_methods.include?(name)
|
215
|
-
class_eval <<-EOS, __FILE__, __LINE__
|
213
|
+
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
216
214
|
def #{name} # def valid_for_signup?
|
217
215
|
valid?('#{context.to_s}'.to_sym) # valid?('signup'.to_sym)
|
218
216
|
end # end
|
219
217
|
EOS
|
220
218
|
end
|
221
|
-
|
222
|
-
all = "all_valid_for_#{context.to_s}?" # all_valid_for_signup?
|
223
|
-
if !self.instance_methods.include?(all)
|
224
|
-
class_eval <<-EOS, __FILE__, __LINE__
|
225
|
-
def #{all} # def all_valid_for_signup?
|
226
|
-
all_valid?('#{context.to_s}'.to_sym) # all_valid?('signup'.to_sym)
|
227
|
-
end # end
|
228
|
-
EOS
|
229
|
-
end
|
230
219
|
end
|
231
220
|
|
232
221
|
# Create a new validator of the given klazz and push it onto the
|
@@ -5,8 +5,10 @@ module CouchRest
|
|
5
5
|
module CastedModel
|
6
6
|
|
7
7
|
def self.included(base)
|
8
|
+
base.send(:include, ::CouchRest::Callbacks)
|
8
9
|
base.send(:include, ::CouchRest::Mixins::Properties)
|
9
10
|
base.send(:attr_accessor, :casted_by)
|
11
|
+
base.send(:attr_accessor, :document_saved)
|
10
12
|
end
|
11
13
|
|
12
14
|
def initialize(keys={})
|
@@ -26,5 +28,31 @@ module CouchRest
|
|
26
28
|
def [] key
|
27
29
|
super(key.to_s)
|
28
30
|
end
|
31
|
+
|
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
|
+
# False if the casted model has already
|
40
|
+
# been saved in the containing document
|
41
|
+
def new?
|
42
|
+
!@document_saved
|
43
|
+
end
|
44
|
+
alias :new_record? :new?
|
45
|
+
|
46
|
+
# Sets the attributes from a hash
|
47
|
+
def update_attributes_without_saving(hash)
|
48
|
+
hash.each do |k, v|
|
49
|
+
raise NoMethodError, "#{k}= method not available, use property :#{k}" unless self.respond_to?("#{k}=")
|
50
|
+
end
|
51
|
+
hash.each do |k, v|
|
52
|
+
self.send("#{k}=",v)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
alias :attributes= :update_attributes_without_saving
|
56
|
+
|
29
57
|
end
|
30
|
-
end
|
58
|
+
end
|
@@ -21,7 +21,7 @@ module CouchRest
|
|
21
21
|
|
22
22
|
def self.inherited(subklass)
|
23
23
|
subklass.send(:include, CouchRest::Mixins::Properties)
|
24
|
-
subklass.class_eval <<-EOS, __FILE__, __LINE__
|
24
|
+
subklass.class_eval <<-EOS, __FILE__, __LINE__ + 1
|
25
25
|
def self.inherited(subklass)
|
26
26
|
subklass.properties = self.properties.dup
|
27
27
|
end
|
@@ -33,10 +33,10 @@ module CouchRest
|
|
33
33
|
attr_accessor :casted_by
|
34
34
|
|
35
35
|
# Callbacks
|
36
|
-
define_callbacks :create
|
37
|
-
define_callbacks :save
|
38
|
-
define_callbacks :update
|
39
|
-
define_callbacks :destroy
|
36
|
+
define_callbacks :create, "result == :halt"
|
37
|
+
define_callbacks :save, "result == :halt"
|
38
|
+
define_callbacks :update, "result == :halt"
|
39
|
+
define_callbacks :destroy, "result == :halt"
|
40
40
|
|
41
41
|
def initialize(passed_keys={})
|
42
42
|
apply_defaults # defined in CouchRest::Mixins::Properties
|
@@ -76,17 +76,17 @@ module CouchRest
|
|
76
76
|
# on the document whenever saving occurs. CouchRest uses a pretty
|
77
77
|
# decent time format by default. See Time#to_json
|
78
78
|
def self.timestamps!
|
79
|
-
class_eval <<-EOS, __FILE__, __LINE__
|
79
|
+
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
80
80
|
property(:updated_at, :read_only => true, :cast_as => 'Time', :auto_validation => false)
|
81
81
|
property(:created_at, :read_only => true, :cast_as => 'Time', :auto_validation => false)
|
82
82
|
|
83
|
-
|
83
|
+
set_callback :save, :before do |object|
|
84
84
|
object['updated_at'] = Time.now
|
85
|
-
object['created_at'] = object['updated_at'] if object.
|
85
|
+
object['created_at'] = object['updated_at'] if object.new?
|
86
86
|
end
|
87
87
|
EOS
|
88
88
|
end
|
89
|
-
|
89
|
+
|
90
90
|
# Name a method that will be called before the document is first saved,
|
91
91
|
# which returns a string to be used for the document's <tt>_id</tt>.
|
92
92
|
# Because CouchDB enforces a constraint that each id must be unique,
|
@@ -128,17 +128,36 @@ module CouchRest
|
|
128
128
|
self.class.properties
|
129
129
|
end
|
130
130
|
|
131
|
+
# Gets a reference to the actual document in the DB
|
132
|
+
# Calls up to the next document if there is one,
|
133
|
+
# Otherwise we're at the top and we return self
|
134
|
+
def base_doc
|
135
|
+
return self if base_doc?
|
136
|
+
@casted_by.base_doc
|
137
|
+
end
|
138
|
+
|
139
|
+
# Checks if we're the top document
|
140
|
+
def base_doc?
|
141
|
+
!@casted_by
|
142
|
+
end
|
143
|
+
|
131
144
|
# Takes a hash as argument, and applies the values by using writer methods
|
132
145
|
# for each key. It doesn't save the document at the end. Raises a NoMethodError if the corresponding methods are
|
133
146
|
# missing. In case of error, no attributes are changed.
|
134
147
|
def update_attributes_without_saving(hash)
|
135
|
-
|
148
|
+
# remove attributes that cannot be updated, silently ignoring them
|
149
|
+
# which matches Rails behavior when, for instance, setting created_at.
|
150
|
+
# make a copy, we don't want to change arguments
|
151
|
+
attrs = hash.dup
|
152
|
+
%w[_id _rev created_at updated_at].each {|attr| attrs.delete(attr)}
|
153
|
+
attrs.each do |k, v|
|
136
154
|
raise NoMethodError, "#{k}= method not available, use property :#{k}" unless self.respond_to?("#{k}=")
|
137
155
|
end
|
138
|
-
|
156
|
+
attrs.each do |k, v|
|
139
157
|
self.send("#{k}=",v)
|
140
158
|
end
|
141
159
|
end
|
160
|
+
alias :attributes= :update_attributes_without_saving
|
142
161
|
|
143
162
|
# Takes a hash as argument, and applies the values by using writer methods
|
144
163
|
# for each key. Raises a NoMethodError if the corresponding methods are
|
@@ -149,7 +168,8 @@ module CouchRest
|
|
149
168
|
end
|
150
169
|
|
151
170
|
# for compatibility with old-school frameworks
|
152
|
-
alias :new_record? :
|
171
|
+
alias :new_record? :new?
|
172
|
+
alias :new_document? :new?
|
153
173
|
|
154
174
|
# Trigger the callbacks (before, after, around)
|
155
175
|
# and create the document
|
@@ -170,7 +190,7 @@ module CouchRest
|
|
170
190
|
# unlike save, create returns the newly created document
|
171
191
|
def create_without_callbacks(bulk =false)
|
172
192
|
raise ArgumentError, "a document requires a database to be created to (The document or the #{self.class} default database were not set)" unless database
|
173
|
-
set_unique_id if
|
193
|
+
set_unique_id if new? && self.respond_to?(:set_unique_id)
|
174
194
|
result = database.save_doc(self, bulk)
|
175
195
|
(result["ok"] == true) ? self : false
|
176
196
|
end
|
@@ -185,7 +205,7 @@ module CouchRest
|
|
185
205
|
# only if the document isn't new
|
186
206
|
def update(bulk = false)
|
187
207
|
caught = catch(:halt) do
|
188
|
-
if self.
|
208
|
+
if self.new?
|
189
209
|
save(bulk)
|
190
210
|
else
|
191
211
|
_run_update_callbacks do
|
@@ -201,7 +221,7 @@ module CouchRest
|
|
201
221
|
# and save the document
|
202
222
|
def save(bulk = false)
|
203
223
|
caught = catch(:halt) do
|
204
|
-
if self.
|
224
|
+
if self.new?
|
205
225
|
_run_save_callbacks do
|
206
226
|
save_without_callbacks(bulk)
|
207
227
|
end
|
@@ -215,15 +235,17 @@ module CouchRest
|
|
215
235
|
# Returns a boolean value
|
216
236
|
def save_without_callbacks(bulk = false)
|
217
237
|
raise ArgumentError, "a document requires a database to be saved to (The document or the #{self.class} default database were not set)" unless database
|
218
|
-
set_unique_id if
|
238
|
+
set_unique_id if new? && self.respond_to?(:set_unique_id)
|
219
239
|
result = database.save_doc(self, bulk)
|
220
|
-
|
240
|
+
mark_as_saved
|
241
|
+
true
|
221
242
|
end
|
222
243
|
|
223
244
|
# Saves the document to the db using save. Raises an exception
|
224
245
|
# if the document is not saved properly.
|
225
246
|
def save!
|
226
247
|
raise "#{self.inspect} failed to save" unless self.save
|
248
|
+
true
|
227
249
|
end
|
228
250
|
|
229
251
|
# Deletes the document from the database. Runs the :destroy callbacks.
|
@@ -242,5 +264,22 @@ module CouchRest
|
|
242
264
|
end
|
243
265
|
end
|
244
266
|
|
267
|
+
protected
|
268
|
+
|
269
|
+
# Set document_saved flag on all casted models to true
|
270
|
+
def mark_as_saved
|
271
|
+
self.each do |key, prop|
|
272
|
+
if prop.is_a?(Array)
|
273
|
+
prop.each do |item|
|
274
|
+
if item.respond_to?(:document_saved)
|
275
|
+
item.send(:document_saved=, true)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
elsif prop.respond_to?(:document_saved)
|
279
|
+
prop.send(:document_saved=, true)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
245
284
|
end
|
246
285
|
end
|