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)
- TYPES =
{ :text => "", :number => 0, :decimal => 0.0, :boolean => true }
Class Method Summary collapse
- .base_class ⇒ Object
-
.count(search_params = {}) ⇒ Object
Retrieves the count of the number of objects in the CouchDB database, based on the search parameters given.
-
.count_all ⇒ Object
Retrieves the count of the number of objects in the CouchDB database, irrespective of any search criteria.
-
.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.
-
.find_from_url(url) ⇒ 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.
-
.has_one(name, options = {}) ⇒ Object
Defines a single object which is a ‘child’ 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(options = {}) ⇒ Object
Deletes a document from a CouchDB database.
-
#initialize(params = {}) {|_self| ... } ⇒ Base
constructor
Initializes an ActiveCouch::Base object.
-
#marshal_dump ⇒ Object
:nodoc:.
-
#marshal_load(str) ⇒ Object
:nodoc:.
-
#new? ⇒ Boolean
Checks to see if a document has been persisted in a CouchDB database.
-
#save(options = {}) ⇒ 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 = {}) {|_self| ... } ⇒ Base
Initializes an ActiveCouch::Base object. The constructor accepts both a hash, as well as a block to initialize attributes
Examples:
class Person < ActiveCouch::Base
has :name
end
person1 = Person.new(:name => "McLovin")
person1.name # => "McLovin"
person2 = Person.new do |p|
p.name = "Seth"
end
person2.name # => "Seth"
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/active_couch/base.rb', line 23 def initialize(params = {}) # Object instance variable @attributes = {}; @associations = {}; @callbacks = Hash.new; @connection = self.class.connection # Initialize local variables from class instance variables 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 # First, initialize all the attributes klass_atts.each_key do |property| @attributes[property] = klass_atts[property] self.instance_eval "def #{property}; attributes[:#{property}]; end" self.instance_eval "def #{property}=(val); attributes[:#{property}] = val; end" # These are special attributes which need aliases (for now, it's _id and _rev) if property.to_s[0,1] == '_' aliased_prop = property.to_s.slice(1, property.to_s.size) self.instance_eval "def #{aliased_prop}; self.#{property}; end" self.instance_eval "def #{aliased_prop}=(val); self.#{property}=(val); end" end end # Then, initialize all the associations klass_assocs.each_key do |k| @associations[k] = klass_assocs[k] self.instance_eval "def #{k}; @#{k} ||= []; 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_#{k.singularize}(val); @#{k} = #{k} << val; end" end # Finally, all the calbacks klass_callbacks.each_key do |k| @callbacks[k] = klass_callbacks[k].dup end # Set any instance variables if any, which are present in the params hash from_hash(params) # Handle the block, which can also be used to initialize the object yield self if block_given? end |
Class Method Details
.base_class ⇒ Object
505 506 507 |
# File 'lib/active_couch/base.rb', line 505 def base_class class_of_active_couch_descendant(self) end |
.count(search_params = {}) ⇒ Object
Retrieves the count of the number of objects in the CouchDB database, based on the search parameters given.
Example:
class Person < ActiveCouch::Base
has :name
end
# This returns the count of the number of objects
people_count = Person.count(:params => {:name => "McLovin"})
397 398 399 400 401 402 |
# File 'lib/active_couch/base.rb', line 397 def count(search_params = {}) path = "/#{database_name}/_view/#{query_string(search_params[:params], {:limit => 0})}" result = connection.get(path) JSON.parse(result)['total_rows'].to_i end |
.count_all ⇒ Object
Retrieves the count of the number of objects in the CouchDB database, irrespective of any search criteria
Example:
class Person < ActiveCouch::Base
has :name
end
# This returns the count of the number of objects
people_count = Person.count_all
414 415 416 417 |
# File 'lib/active_couch/base.rb', line 414 def count_all result = connection.get("/#{database_name}") JSON.parse(result)['doc_count'].to_i 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
430 431 432 433 434 435 436 437 438 |
# File 'lib/active_couch/base.rb', line 430 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.
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/active_couch/base.rb', line 199 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 = parent.database_name.singularize contained << '_' end "#{contained}#{base.name.pluralize.demodulize.underscore}" 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
479 480 481 482 483 484 485 486 |
# File 'lib/active_couch/base.rb', line 479 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')
449 450 451 452 453 454 455 456 |
# File 'lib/active_couch/base.rb', line 449 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 =~ /20[0,2]/).nil? 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"})
349 350 351 352 353 354 355 356 357 358 |
# File 'lib/active_couch/base.rb', line 349 def find(*arguments) scope = arguments.slice!(0) search_params = arguments.slice!(0) || {} case scope when :all then find_every(search_params) when :first then find_every(search_params, {:limit => 1}).first else find_one(scope) end end |
.find_from_url(url) ⇒ Object
Retrieves one or more object(s) from a CouchDB database, based on the search parameters given. This method is similar to the find_by_sql method in ActiveRecord, in a way that instead of using any conditions, we use a raw URL to query a CouchDB view.
Example:
class Person < ActiveCouch::Base
has :name
end
# This returns a single instance of an ActiveCouch::Base subclass
people = Person.find_from_url("/people/_view/by_name/by_name?key=%22Mclovin%22")
372 373 374 375 376 377 378 379 380 381 382 383 384 385 |
# File 'lib/active_couch/base.rb', line 372 def find_from_url(url) # If the url contains the word '_view' it means it will return objects as an array, # how ever if it doesn't it means the user is getting an ID-based url like /properties/abcd # which will only return a single object if url =~ /_view/ instantiate_collection(connection.get(url)) else begin instantiate_object(connection.get(url)) rescue ResourceNotFound nil end 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"
330 331 332 333 334 |
# File 'lib/active_couch/base.rb', line 330 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
267 268 269 270 271 272 273 274 275 |
# File 'lib/active_couch/base.rb', line 267 def has(name, = {}) unless name.is_a?(String) || name.is_a?(Symbol) raise ArgumentError, "#{name} is neither a String nor a Symbol" end # Set the attributes value to options[:with_default_value] # In the constructor, this will be used to initialize the value of # the 'name' instance variable to the value in the hash @attributes[name] = [:with_default_value] || TYPES[:which_is] 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
291 292 293 294 295 296 297 |
# File 'lib/active_couch/base.rb', line 291 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] = get_klass(name, ) end |
.has_one(name, options = {}) ⇒ Object
Defines a single object which is a ‘child’ of this class. The has_one 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 Child < ActiveCouch::Base
has :name
end
class GrandParent < ActiveCouch::Base
has_one :child
end
312 313 314 315 316 317 318 |
# File 'lib/active_couch/base.rb', line 312 def has_one(name, = {}) unless name.is_a?(String) || name.is_a?(Symbol) raise ArgumentError, "#{name} is neither a String nor a Symbol" end @associations[name] = get_klass(name, ) end |
.inherited(subklass) ⇒ Object
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 |
# File 'lib/active_couch/base.rb', line 488 def inherited(subklass) subklass.class_eval do include ActiveCouch::Callbacks end subklass.instance_eval do @attributes = { :_id => nil, :_rev => nil } @associations = {} @callbacks = Hash.new([]) @connection = ActiveCouch::Base.instance_variable_get('@connection') end 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
225 226 227 |
# File 'lib/active_couch/base.rb', line 225 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
239 240 241 |
# File 'lib/active_couch/base.rb', line 239 def site(site) @connection = Connection.new(site) end |
Instance Method Details
#delete(options = {}) ⇒ 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
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/active_couch/base.rb', line 148 def delete( = {}) database = [:from_database] || self.class.database_name 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("/#{database}/#{id}?rev=#{rev}") # Set the id and rev to nil, since the object has been successfully deleted from CouchDB if response.code =~ /20[0,2]/ self.id = nil; self.rev = nil true else false end end |
#marshal_dump ⇒ Object
:nodoc:
166 167 168 169 |
# File 'lib/active_couch/base.rb', line 166 def marshal_dump # :nodoc: # Deflate using Zlib self.to_json end |
#marshal_load(str) ⇒ Object
:nodoc:
171 172 173 174 175 176 177 178 |
# File 'lib/active_couch/base.rb', line 171 def marshal_load(str) # :nodoc: self.instance_eval do # Inflate first, and then parse the JSON hash = JSON.parse(str) initialize(hash) end self 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
136 137 138 |
# File 'lib/active_couch/base.rb', line 136 def new? rev.nil? end |
#save(options = {}) ⇒ 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
108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/active_couch/base.rb', line 108 def save( = {}) database = [:to_database] || self.class.database_name if id response = connection.put("/#{database}/#{id}", to_json) else response = connection.post("/#{database}", 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"}
83 84 85 86 87 88 89 90 91 |
# File 'lib/active_couch/base.rb', line 83 def to_json hash = {} # First merge the attributes... hash.merge!(attributes.reject{ |k,v| v.nil? }) # ...and then the associations associations.each_key { |name| hash.merge!({ name => self.__send__(name.to_s) }) } # and by the Power of Grayskull, convert the hash to json hash.to_json end |