Class: ActiveCouch::Base
- Inherits:
-
Object
- Object
- ActiveCouch::Base
- Defined in:
- lib/active_couch/base.rb
Constant Summary collapse
- SPECIAL_MEMBERS =
%w(attributes associations connection callbacks)
- DEFAULT_ATTRIBUTES =
%w(id rev)
Class Method Summary collapse
- .base_class ⇒ Object
-
.create(arguments) ⇒ Object
Initializes a new subclass of ActiveCouch::Base and saves in the CouchDB database as a new document.
-
.database_name ⇒ Object
Returns the CouchDB database name that’s backing this model.
-
.define_attr_method(name, value = nil, &block) ⇒ Object
Defines an “attribute” method.
-
.delete(options = {}) ⇒ Object
Deletes a document from the CouchDB database, based on the id and rev parameters passed to it.
-
.find(*arguments) ⇒ Object
Retrieves one or more object(s) from a CouchDB database, based on the search parameters given.
-
.from_json(json) ⇒ Object
Initializes an object of a subclass of ActiveCouch::Base based on a JSON representation of the object.
-
.has(name, options = {}) ⇒ Object
Defines an attribute for a subclass of ActiveCouch::Base.
-
.has_many(name, options = {}) ⇒ Object
Defines an array of objects which are ‘children’ of this class.
- .inherited(subklass) ⇒ Object
-
.set_database_name(database = nil, &block) ⇒ Object
(also: database_name=)
Sets the database name to the given value, or (if the value is nil or false) to the value returned by the given block.
-
.site(site) ⇒ Object
Sets the site which the ActiveCouch object has to connect to, which initializes an ActiveCouch::Connection object.
Instance Method Summary collapse
-
#delete ⇒ Object
Deletes a document from a CouchDB database.
-
#initialize(params = {}) ⇒ Base
constructor
A new instance of Base.
-
#new? ⇒ Boolean
Checks to see if a document has been persisted in a CouchDB database.
-
#save ⇒ Object
Saves a document into a CouchDB database.
-
#to_json ⇒ Object
Generates a JSON representation of an instance of a subclass of ActiveCouch::Base.
Constructor Details
#initialize(params = {}) ⇒ Base
Returns a new instance of Base.
6 7 8 9 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 |
# File 'lib/active_couch/base.rb', line 6 def initialize(params = {}) # Object instance variable @attributes = {}; @associations = {}; @callbacks = Hash.new; @connection = self.class.connection klass_atts = self.class.attributes; klass_assocs = self.class.associations; klass_callbacks = self.class.callbacks # ActiveCouch::Connection object will be readable in every # object instantiated from a subclass of ActiveCouch::Base SPECIAL_MEMBERS.each do |k| self.instance_eval "def #{k}; @#{k}; end" end klass_atts.each_key do |k| @attributes[k] = klass_atts[k].dup self.instance_eval "def #{k}; attributes[:#{k}].value; end" self.instance_eval "def #{k}=(val); attributes[:#{k}].value = val; end" end klass_assocs.each_key do |k| @associations[k] = HasManyAssociation.new(klass_assocs[k].name, :class => klass_assocs[k].klass) self.instance_eval "def #{k}; associations[:#{k}].container; end" # If you have has_many :people, this will add a method called add_person to the object instantiated # from the class self.instance_eval "def add_#{Inflector.singularize(k)}(val); associations[:#{k}].push(val); end" end klass_callbacks.each_key do |k| @callbacks[k] = klass_callbacks[k].dup end DEFAULT_ATTRIBUTES.each do |x| self.instance_eval "def #{x}; _#{x}; end" self.instance_eval "def #{x}=(val); self._#{x}=(val); end" end # Set any instance variables if any, which are present in the params hash from_hash(params) end |
Class Method Details
.base_class ⇒ Object
382 383 384 |
# File 'lib/active_couch/base.rb', line 382 def base_class class_of_active_couch_descendant(self) end |
.create(arguments) ⇒ Object
Initializes a new subclass of ActiveCouch::Base and saves in the CouchDB database as a new document
Example:
class Person < ActiveCouch::Base
has :name
end
person = Person.create(:name => "McLovin")
person.id.nil? # false
person.new? # false
307 308 309 310 311 312 313 314 315 |
# File 'lib/active_couch/base.rb', line 307 def create(arguments) unless arguments.is_a?(Hash) raise ArgumentError, "The arguments must be a Hash" else new_record = self.new(arguments) new_record.save new_record end end |
.database_name ⇒ Object
Returns the CouchDB database name that’s backing this model. The database name is guessed from the name of the class somewhat similar to ActiveRecord conventions.
Examples:
class Invoice < ActiveCouch::Base; end;
file class database_name
invoice.rb Invoice invoices
class Invoice < ActiveCouch::Base; class Lineitem < ActiveCouch::Base; end; end;
file class database_name
invoice.rb Invoice::Lineitem invoice_lineitems
module Invoice; class Lineitem < ActiveCouch::Base; end; end;
file class database_name
invoice/lineitem.rb Invoice::Lineitem lineitems
You can override this method or use set_database_name
to override this class method to allow for names that can’t be inferred.
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/active_couch/base.rb', line 160 def database_name base = base_class name = (unless self == base base.database_name else # Nested classes are prefixed with singular parent database name. if parent < ActiveCouch::Base contained = Inflector.singularize(parent.database_name) contained << '_' end "#{contained}#{Inflector.underscore(Inflector.demodulize(Inflector.pluralize(base.name)))}" end) set_database_name(name) name end |
.define_attr_method(name, value = nil, &block) ⇒ Object
Defines an “attribute” method. A new (class) method will be created with the given name. If a value is specified, the new method will return that value (as a string). Otherwise, the given block will be used to compute the value of the method.
The original method, if it exists, will be aliased, with the new name being prefixed with “original_”. This allows the new method to access the original value.
This method is stolen from ActiveRecord.
Example:
class Foo < ActiveCouch::Base
define_attr_method :database_name, 'foo'
# OR
define_attr_method(:database_name) do
original_database_name + '_legacy'
end
end
356 357 358 359 360 361 362 363 |
# File 'lib/active_couch/base.rb', line 356 def define_attr_method(name, value = nil, &block) .send(:alias_method, "original_#{name}", name) if block_given? name, &block else .class_eval "def #{name}; #{value.to_s.inspect}; end" end end |
.delete(options = {}) ⇒ Object
Deletes a document from the CouchDB database, based on the id and rev parameters passed to it. Returns true if the document has been deleted
Example:
class Person < ActiveCouch::Base
has :name
end
Person.delete(:id => 'abc-def', :rev => '1235')
326 327 328 329 330 331 332 333 |
# File 'lib/active_couch/base.rb', line 326 def delete( = {}) if .nil? || !.has_key?(:id) || !.has_key?(:rev) raise ArgumentError, "You must specify both an id and a rev for the document to be deleted" end response = connection.delete("/#{self.database_name}/#{[:id]}?rev=#{[:rev]}") # Returns true if the response.code == '202' end |
.find(*arguments) ⇒ Object
Retrieves one or more object(s) from a CouchDB database, based on the search parameters given.
Example:
class Person < ActiveCouch::Base
has :name
end
# This returns a single instance of an ActiveCouch::Base subclass
people = Person.find(:first, :params => {:name => "McLovin"})
# This returns an array of ActiveCouch::Base subclass instances
person = Person.find(:all, :params => {:name => "McLovin"})
285 286 287 288 289 290 291 292 293 294 |
# File 'lib/active_couch/base.rb', line 285 def find(*arguments) scope = arguments.slice!(0) = arguments.slice!(0) || {} case scope when :all then find_every() when :first then find_every().first else raise ArgumentError("find must have the first parameter as either :all or :first") end end |
.from_json(json) ⇒ Object
Initializes an object of a subclass of ActiveCouch::Base based on a JSON representation of the object.
Example:
class Person < ActiveCouch::Base
has :name
end
person = Person.from_json('{"name":"McLovin"}')
person.name # "McLovin"
266 267 268 269 270 |
# File 'lib/active_couch/base.rb', line 266 def from_json(json) hash = JSON.parse(json) # Create new based on parsed self.new(hash) end |
.has(name, options = {}) ⇒ Object
Defines an attribute for a subclass of ActiveCouch::Base. The parameters for this method include name, which is the name of the attribute as well as an options hash.
The options hash can contain the key ‘which_is’ which can have possible values :text, :decimal, :number. It can also contain the key ‘with_default_value’ which can set a default value for each attribute defined in the subclass of ActiveCouch::Base
Examples:
class Person < ActiveCouch::Base
has :name
end
person = Person.new
p.name.methods.include?(:name) # true
p.name.methods.include?(:name=) # false
class AgedPerson < ActiveCouch::Base
has :age, :which_is => :number, :with_default_value = 18
end
person = AgedPerson.new
person.age # 18
228 229 230 231 232 233 |
# File 'lib/active_couch/base.rb', line 228 def has(name, = {}) unless name.is_a?(String) || name.is_a?(Symbol) raise ArgumentError, "#{name} is neither a String nor a Symbol" end @attributes[name] = Attribute.new(name, ) end |
.has_many(name, options = {}) ⇒ Object
Defines an array of objects which are ‘children’ of this class. The has_many function guesses the class of the child, based on the name of the association, but can be over-ridden by the :class key in the options hash.
Examples:
class Person < ActiveCouch::Base
has :name
end
class GrandPerson < ActiveCouch::Base
has_many :people # which will create an empty array which can contain
# Person objects
end
249 250 251 252 253 254 |
# File 'lib/active_couch/base.rb', line 249 def has_many(name, = {}) unless name.is_a?(String) || name.is_a?(Symbol) raise ArgumentError, "#{name} is neither a String nor a Symbol" end @associations[name] = HasManyAssociation.new(name, ) end |
.inherited(subklass) ⇒ Object
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
# File 'lib/active_couch/base.rb', line 365 def inherited(subklass) subklass.class_eval do include ActiveCouch::Callbacks end # TODO: Need a cleaner way to do this subklass.instance_variable_set "@attributes", { :_id => Attribute.new(:_id, :with_default_value => nil), :_rev => Attribute.new(:_rev, :with_default_value => nil) } subklass.instance_variable_set "@associations", {} subklass.instance_variable_set "@callbacks", Hash.new([]) subklass.instance_variable_set "@connections", nil SPECIAL_MEMBERS.each do |k| subklass.instance_eval "def #{k}; @#{k}; end" end end |
.set_database_name(database = nil, &block) ⇒ Object Also known as: database_name=
Sets the database name to the given value, or (if the value is nil or false) to the value returned by the given block. Useful for setting database names that can’t be automatically inferred from the class name.
This method is aliased as database_name=
.
Example:
class Post < ActiveCouch::Base
set_database_name 'legacy_posts'
end
186 187 188 |
# File 'lib/active_couch/base.rb', line 186 def set_database_name(database = nil, &block) define_attr_method(:database_name, database, &block) end |
.site(site) ⇒ Object
Sets the site which the ActiveCouch object has to connect to, which initializes an ActiveCouch::Connection object.
Example:
class Person < ActiveCouch::Base
site 'localhost:5984'
end
Person.connection.nil? # false
200 201 202 |
# File 'lib/active_couch/base.rb', line 200 def site(site) @connection = Connection.new(site) end |
Instance Method Details
#delete ⇒ Object
Deletes a document from a CouchDB database. This is an instance-level delete method. Example:
class Person < ActiveCouch::Base
has :name
end
person = Person.create(:name => 'McLovin')
person.delete # true
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/active_couch/base.rb', line 124 def delete if new? raise ArgumentError, "You must specify a revision for the document to be deleted" elsif id.nil? raise ArgumentError, "You must specify an ID for the document to be deleted" end response = connection.delete("/#{self.class.database_name}/#{id}?rev=#{rev}") # Set the id and rev to nil, since the object has been successfully deleted from CouchDB if response.code == '202' self.id = nil; self.rev = nil true else false end end |
#new? ⇒ Boolean
Checks to see if a document has been persisted in a CouchDB database. If a document has been retrieved from CouchDB, or has been persisted in a CouchDB database, the attribute _rev would not be nil.
Examples:
class Person < ActiveCouch::Base
has :name, :which_is => :text
end
person = Person.new(:name => 'McLovin')
person.id = 'abc'
person.save # true
person.new? # false
112 113 114 |
# File 'lib/active_couch/base.rb', line 112 def new? rev.nil? end |
#save ⇒ Object
Saves a document into a CouchDB database. A document can be saved in two ways. One if it has been set an ID by the user, in which case the connection object needs to use an HTTP PUT request to the URL /database/user_generated_id. For the document needs a CouchDB-generated ID, the connection object needs to use an HTTP POST request to the URL /database.
Examples:
class Person < ActiveCouch::Base
has :name, :which_is => :text
end
person = Person.new(:name => 'McLovin')
person.id = 'abc'
person.save # true
person.new? # false
85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/active_couch/base.rb', line 85 def save if id response = connection.put("/#{self.class.database_name}/#{id}", to_json) else response = connection.post("/#{self.class.database_name}", to_json) end # Parse the JSON obtained from the body... results = JSON.parse(response.body) # ...and set the default id and rev attributes DEFAULT_ATTRIBUTES.each { |a| self.__send__("#{a}=", results[a]) } # Response sent will be 201, if the save was successful [201 corresponds to 'created'] return response.code == '201' end |
#to_json ⇒ Object
Generates a JSON representation of an instance of a subclass of ActiveCouch::Base. Ignores attributes which have a nil value.
Examples:
class Person < ActiveCouch::Base
has :name, :which_is => :text, :with_default_value => "McLovin"
end
person = Person.new
person.to_json # {"name":"McLovin"}
class AgedPerson < ActiveCouch::Base
has :age, :which_is => :decimal, :with_default_value => 3.5
end
aged_person = AgedPerson.new
aged_person.id = 'abc-def'
aged_person.to_json # {"age":3.5, "_id":"abc-def"}
61 62 63 64 65 66 67 68 |
# File 'lib/active_couch/base.rb', line 61 def to_json hash = {} attributes.each_value { |v| hash.merge!(v.to_hash) unless v.nil? } associations.each_value { |v| hash.merge!(v.to_hash) } # and by the Power of Grayskull, convert the hash to json hash.to_json end |