Class: RelaxDB::Document
- Inherits:
-
Object
- Object
- RelaxDB::Document
- Defined in:
- lib/relaxdb/document.rb
Instance Attribute Summary collapse
-
#errors ⇒ Object
Used to store validation messages.
Class Method Summary collapse
- .after_save(callback) ⇒ Object
- .after_save_callbacks ⇒ Object
- .all ⇒ Object
- .all_relationships ⇒ Object
-
.before_save(callback) ⇒ Object
Callbacks - define these in a module and mix’em’in ?.
- .before_save_callbacks ⇒ Object
- .belongs_to(relationship, opts = {}) ⇒ Object
- .belongs_to_rels ⇒ Object
- .has_many(relationship, opts = {}) ⇒ Object
- .has_many_rels ⇒ Object
- .has_one(relationship) ⇒ Object
- .has_one_rels ⇒ Object
- .paginate_by(page_params, *view_keys) {|paginate_params| ... } ⇒ Object
- .properties ⇒ Object
-
.property(prop, opts = {}) ⇒ Object
Define properties and property methods.
-
.references_many(relationship, opts = {}) ⇒ Object
Deprecated.
- .references_many_rels ⇒ Object
Instance Method Summary collapse
-
#==(other) ⇒ Object
Returns true if CouchDB considers other to be the same as self.
-
#add_denormalised_data(data, relationship, opts) ⇒ Object
quick n’ dirty denormalisation - explicit denormalisation will probably become a permanent fixture of RelaxDB, but quite likely in a different form to this one.
- #after_save ⇒ Object
- #before_save ⇒ Object
- #create_or_get_proxy(klass, relationship, opts = nil) ⇒ Object
-
#destroy! ⇒ Object
destroy! nullifies all relationships with peers and children before deleting itself in CouchDB The nullification and deletion are not performed in a transaction.
-
#initialize(hash = {}) ⇒ Document
constructor
A new instance of Document.
- #inspect ⇒ Object
- #properties ⇒ Object
-
#save ⇒ Object
Order changed as of 30/10/2008 to be consistent with ActiveRecord Not yet sure of final implemention for hooks - may lean more towards DM than AR.
- #set_attributes(data) ⇒ Object
- #set_created_at ⇒ Object
- #to_json ⇒ Object
- #to_param ⇒ Object (also: #id)
-
#unsaved? ⇒ Boolean
(also: #new_record?, #new_document?)
Hmm.
- #validate ⇒ Object
- #validates? ⇒ Boolean
Constructor Details
#initialize(hash = {}) ⇒ Document
Returns a new instance of Document.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/relaxdb/document.rb', line 60 def initialize(hash={}) # The default _id will be overwritten if loaded from CouchDB self._id = UuidGenerator.uuid @errors = Errors.new # Set default properties if this object has not known CouchDB unless hash["_rev"] properties.each do |prop| if methods.include?("set_default_#{prop}") send("set_default_#{prop}") end end end set_attributes(hash) end |
Instance Attribute Details
#errors ⇒ Object
Used to store validation messages
6 7 8 |
# File 'lib/relaxdb/document.rb', line 6 def errors @errors end |
Class Method Details
.after_save(callback) ⇒ Object
350 351 352 |
# File 'lib/relaxdb/document.rb', line 350 def self.after_save(callback) after_save_callbacks << callback end |
.after_save_callbacks ⇒ Object
354 355 356 |
# File 'lib/relaxdb/document.rb', line 354 def self.after_save_callbacks @after_save_callbacks ||= [] end |
.all ⇒ Object
307 308 309 |
# File 'lib/relaxdb/document.rb', line 307 def self.all @all_delegator ||= AllDelegator.new(self.name) end |
.all_relationships ⇒ Object
303 304 305 |
# File 'lib/relaxdb/document.rb', line 303 def self.all_relationships belongs_to_rels + has_one_rels + has_many_rels + references_many_rels end |
.before_save(callback) ⇒ Object
Callbacks - define these in a module and mix’em’in ?
335 336 337 |
# File 'lib/relaxdb/document.rb', line 335 def self.before_save(callback) before_save_callbacks << callback end |
.before_save_callbacks ⇒ Object
339 340 341 |
# File 'lib/relaxdb/document.rb', line 339 def self.before_save_callbacks @before_save ||= [] end |
.belongs_to(relationship, opts = {}) ⇒ Object
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'lib/relaxdb/document.rb', line 274 def self.belongs_to(relationship, opts={}) @belongs_to_rels ||= {} @belongs_to_rels[relationship] = opts define_method(relationship) do create_or_get_proxy(BelongsToProxy, relationship).target end define_method("#{relationship}=") do |new_target| create_or_get_proxy(BelongsToProxy, relationship).target = new_target end # Allows all writers to be invoked from the hash passed to initialize define_method("#{relationship}_id=") do |id| instance_variable_set("@#{relationship}_id".to_sym, id) end # Allows belongs_to relationships to be used by the paginator define_method("#{relationship}_id") do instance_variable_get("@#{relationship}_id") end end |
.belongs_to_rels ⇒ Object
298 299 300 301 |
# File 'lib/relaxdb/document.rb', line 298 def self.belongs_to_rels # Don't force clients to check that it's instantiated @belongs_to_rels ||= {} end |
.has_many(relationship, opts = {}) ⇒ Object
239 240 241 242 243 244 245 246 247 248 249 250 |
# File 'lib/relaxdb/document.rb', line 239 def self.has_many(relationship, opts={}) @has_many_rels ||= [] @has_many_rels << relationship define_method(relationship) do create_or_get_proxy(HasManyProxy, relationship, opts) end define_method("#{relationship}=") do raise "You may not currently assign to a has_many relationship - may be implemented" end end |
.has_many_rels ⇒ Object
252 253 254 255 |
# File 'lib/relaxdb/document.rb', line 252 def self.has_many_rels # Don't force clients to check its instantiated @has_many_rels ||= [] end |
.has_one(relationship) ⇒ Object
257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/relaxdb/document.rb', line 257 def self.has_one(relationship) @has_one_rels ||= [] @has_one_rels << relationship define_method(relationship) do create_or_get_proxy(HasOneProxy, relationship).target end define_method("#{relationship}=") do |new_target| create_or_get_proxy(HasOneProxy, relationship).target = new_target end end |
.has_one_rels ⇒ Object
270 271 272 |
# File 'lib/relaxdb/document.rb', line 270 def self.has_one_rels @has_one_rels ||= [] end |
.paginate_by(page_params, *view_keys) {|paginate_params| ... } ⇒ Object
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
# File 'lib/relaxdb/document.rb', line 364 def self.paginate_by(page_params, *view_keys) paginate_params = PaginateParams.new yield paginate_params raise paginate_params.error_msg if paginate_params.invalid? paginator = Paginator.new(paginate_params, page_params) design_doc_name = self.name view = SortedByView.new(design_doc_name, *view_keys) query = Query.new(design_doc_name, view.view_name) query.merge(paginate_params) docs = view.query(query) docs.reverse! if paginate_params.order_inverted? paginator.add_next_and_prev(docs, design_doc_name, view.view_name, view_keys) docs end |
.properties ⇒ Object
46 47 48 49 |
# File 'lib/relaxdb/document.rb', line 46 def self.properties # Ensure that classes that don't define their own properties still function as CouchDB objects @properties ||= [:_id, :_rev] end |
.property(prop, opts = {}) ⇒ Object
Define properties and property methods
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/relaxdb/document.rb', line 10 def self.property(prop, opts={}) # Class instance varibles are not inherited, so the default properties must be explicitly listed # Perhaps a better solution exists. Revise. I think extlib contains a solution for this... @properties ||= [:_id, :_rev] @properties << prop define_method(prop) do instance_variable_get("@#{prop}".to_sym) end define_method("#{prop}=") do |val| instance_variable_set("@#{prop}".to_sym, val) end if opts[:default] define_method("set_default_#{prop}") do default = opts[:default] default = default.is_a?(Proc) ? default.call : default instance_variable_set("@#{prop}".to_sym, default) end end if opts[:validator] define_method("validate_#{prop}") do |prop_val| opts[:validator].call(prop_val) end end if opts[:validation_msg] define_method("#{prop}_validation_msg") do opts[:validation_msg] end end end |
.references_many(relationship, opts = {}) ⇒ Object
Deprecated. This method was experimental and will be removed once multi key GETs are available in CouchDB.
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/relaxdb/document.rb', line 213 def self.references_many(relationship, opts={}) # Treat the representation as a standard property properties << relationship # Keep track of the relationship so peers can be disassociated on destroy @references_many_rels ||= [] @references_many_rels << relationship define_method(relationship) do array_sym = "@#{relationship}".to_sym instance_variable_set(array_sym, []) unless instance_variable_defined? array_sym create_or_get_proxy(RelaxDB::ReferencesManyProxy, relationship, opts) end define_method("#{relationship}=") do |val| # Sharp edge - do not invoke this method instance_variable_set("@#{relationship}".to_sym, val) end end |
.references_many_rels ⇒ Object
234 235 236 237 |
# File 'lib/relaxdb/document.rb', line 234 def self.references_many_rels # Don't force clients to check its instantiated @references_many_rels ||= [] end |
Instance Method Details
#==(other) ⇒ Object
Returns true if CouchDB considers other to be the same as self
207 208 209 |
# File 'lib/relaxdb/document.rb', line 207 def ==(other) other && _id == other._id end |
#add_denormalised_data(data, relationship, opts) ⇒ Object
quick n’ dirty denormalisation - explicit denormalisation will probably become a permanent fixture of RelaxDB, but quite likely in a different form to this one
129 130 131 132 133 134 135 136 137 |
# File 'lib/relaxdb/document.rb', line 129 def add_denormalised_data(data, relationship, opts) obj = send(relationship) if obj opts[:denormalise].each do |prop_name| val = obj.send(prop_name) data["#{relationship}_#{prop_name}"] = val end end end |
#after_save ⇒ Object
358 359 360 361 362 |
# File 'lib/relaxdb/document.rb', line 358 def after_save self.class.after_save_callbacks.each do |callback| callback.is_a?(Proc) ? callback.call(self) : send(callback) end end |
#before_save ⇒ Object
343 344 345 346 347 348 |
# File 'lib/relaxdb/document.rb', line 343 def before_save self.class.before_save_callbacks.each do |callback| resp = callback.is_a?(Proc) ? callback.call(self) : send(callback) return false unless resp end end |
#create_or_get_proxy(klass, relationship, opts = nil) ⇒ Object
196 197 198 199 200 201 202 203 204 |
# File 'lib/relaxdb/document.rb', line 196 def create_or_get_proxy(klass, relationship, opts=nil) proxy_sym = "@proxy_#{relationship}".to_sym proxy = instance_variable_get(proxy_sym) unless proxy proxy = opts ? klass.new(self, relationship, opts) : klass.new(self, relationship) end instance_variable_set(proxy_sym, proxy) proxy end |
#destroy! ⇒ Object
destroy! nullifies all relationships with peers and children before deleting itself in CouchDB The nullification and deletion are not performed in a transaction
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/relaxdb/document.rb', line 314 def destroy! self.class.references_many_rels.each do |rel| send(rel).clear end self.class.has_many_rels.each do |rel| send(rel).clear end self.class.has_one_rels.each do |rel| send("#{rel}=".to_sym, nil) end # Implicitly prevent the object from being resaved by failing to update its revision RelaxDB.db.delete("#{_id}?rev=#{_rev}") self end |
#inspect ⇒ Object
97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/relaxdb/document.rb', line 97 def inspect s = "#<#{self.class}:#{self.object_id}" properties.each do |prop| prop_val = instance_variable_get("@#{prop}".to_sym) s << ", #{prop}: #{prop_val.inspect}" if prop_val end self.class.belongs_to_rels.each do |relationship| id = instance_variable_get("@#{relationship}_id".to_sym) s << ", #{relationship}_id: #{id}" if id end s << ">" end |
#properties ⇒ Object
51 52 53 |
# File 'lib/relaxdb/document.rb', line 51 def properties self.class.properties end |
#save ⇒ Object
Order changed as of 30/10/2008 to be consistent with ActiveRecord Not yet sure of final implemention for hooks - may lean more towards DM than AR
141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/relaxdb/document.rb', line 141 def save return false unless validates? return false unless before_save set_created_at if unsaved? resp = RelaxDB.db.put("#{_id}", to_json) self._rev = JSON.parse(resp.body)["rev"] after_save self end |
#set_attributes(data) ⇒ Object
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/relaxdb/document.rb', line 78 def set_attributes(data) data.each do |key, val| # Only set instance variables on creation - object references are resolved on demand # If the variable name ends in _at try to convert it to a Time if key =~ /_at$/ val = Time.local(*ParseDate.parsedate(val)) rescue val end # Ignore param keys that don't have a corresponding writer # This allows us to comfortably accept a hash containing superflous data # such as a params hash in a controller if methods.include? "#{key}=" send("#{key}=".to_sym, val) end end end |
#set_created_at ⇒ Object
189 190 191 192 193 194 |
# File 'lib/relaxdb/document.rb', line 189 def set_created_at if methods.include? "created_at" # Don't override it if it's already been set @created_at = Time.now if @created_at.nil? end end |
#to_json ⇒ Object
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/relaxdb/document.rb', line 110 def to_json data = {} self.class.belongs_to_rels.each do |relationship, opts| id = instance_variable_get("@#{relationship}_id".to_sym) data["#{relationship}_id"] = id if id if opts[:denormalise] add_denormalised_data(data, relationship, opts) end end properties.each do |prop| prop_val = instance_variable_get("@#{prop}".to_sym) data["#{prop}"] = prop_val if prop_val end data["class"] = self.class.name data.to_json end |
#to_param ⇒ Object Also known as: id
184 185 186 |
# File 'lib/relaxdb/document.rb', line 184 def to_param self._id end |
#unsaved? ⇒ Boolean Also known as: new_record?, new_document?
Hmm. Rename… never_saved? newnew?
178 179 180 |
# File 'lib/relaxdb/document.rb', line 178 def unsaved? @_rev.nil? end |
#validate ⇒ Object
173 174 175 |
# File 'lib/relaxdb/document.rb', line 173 def validate true end |
#validates? ⇒ Boolean
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/relaxdb/document.rb', line 155 def validates? total_success = true properties.each do |prop| if methods.include? "validate_#{prop}" prop_val = instance_variable_get("@#{prop}") success = send("validate_#{prop}", prop_val) rescue false unless success if methods.include? "#{prop}_validation_msg" @errors["#{prop}".to_sym] = send("#{prop}_validation_msg") end end total_success &= success end end total_success &= validate total_success end |