Class: MongoRecord::Base
Overview
A superclass for database collection instances. The API is very similar to ActiveRecord. See #find for examples.
If you override initialize, make sure to call the superclass version, passing it the database row or hash that it was given.
Example:
class MP3Track < MongoRecord::Base
collection_name :mp3_track
fields :artist, :album, :song, :track
def to_s
"artist: #{self.artist}, album: #{self.album}, song: #{self.song}, track: #{track}"
end
end
track = MP3Track.find_by_song('She Blinded Me With Science')
puts track.to_s
The database connection defaults to the global $db. You can set the connection using MongoRecord::Base.connection= and read it with MongoRecord::Base.connection.
# Set the connection to something besides $db
MongoRecord::Base.connection = connect('my-database')
Direct Known Subclasses
Constant Summary collapse
- @@connection =
nil
Class Method Summary collapse
-
.arrays ⇒ Object
Return the names of all instance variables that hold objects declared using has_many.
-
.belongs_to(name, options = {}) ⇒ Object
Tells Mongo that this object belongs to another.
-
.collection ⇒ Object
The collection object for this class, which will be different for every subclass of MongoRecord::Base.
-
.collection_name(coll_name) ⇒ Object
Call this method to set the Mongo collection name for this class.
-
.connection ⇒ Object
Return the database connection.
-
.connection=(val) ⇒ Object
Set the database connection.
-
.count(options = {}) ⇒ Object
Returns the number of matching records.
-
.create(values_hash) ⇒ Object
Creates, saves, and returns a new database object.
-
.delete(id) ⇒ Object
Deletes the record with the given id from the collection.
-
.delete_all(conditions = nil) ⇒ Object
Deletes all records that match
condition, which can be a Mongo-style hash or an ActiveRecord-like hash. -
.destroy(id) ⇒ Object
Load the object with
idand delete it. -
.destroy_all(conditions = nil) ⇒ Object
Destroy all objects that match
conditions. -
.field(*fields) ⇒ Object
(also: fields)
Creates one or more collection fields.
-
.field_names ⇒ Object
Return the field names.
-
.find(*args) ⇒ Object
Find one or more database objects.
-
.find_by_mql(mql) ⇒ Object
(also: find_by_sql)
Returns all records matching mql.
-
.has_and_belongs_to_many(name, options = {}) ⇒ Object
Tells Mongo that this object has and many belongs to another object.
-
.has_many(name, options = {}) ⇒ Object
Tells Mongo about an array of subobjects (which need not be MongoRecord::Subobjects).
-
.has_one(name, options = {}) ⇒ Object
Tell Mongo about a subobject (which need not be a MongoRecord::Subobject).
-
.inherited(subclass) ⇒ Object
Get ready to save information about
subclass. -
.instantiate(row = {}) ⇒ Object
This method only exists so that MongoRecord::Base and ActiveRecord::Base can live side by side.
-
.method_missing(sym, *args) ⇒ Object
Handles find_* methods such as find_by_name, find_all_by_shoe_size, and find_or_create_by_name.
-
.mongo_ivar_names ⇒ Object
Return the names of all fields, subobjects, and arrays.
-
.remove ⇒ Object
Deletes the record with the given id from the collection.
-
.subobjects ⇒ Object
Return the names of all instance variables that hold objects declared using has_one.
-
.update(id, attributes) ⇒ Object
Finds the record from the passed
id, instantly saves it with the passedattributes(if the validation permits it), and returns it. -
.update_all(updates, conditions = nil) ⇒ Object
Not yet implemented.
Instance Method Summary collapse
-
#==(comparison_object) ⇒ Object
Return true if the
comparison_objectis the same object, or is of the same type and has the same id. -
#attributes_from_column_definition ⇒ Object
Does nothing.
-
#create ⇒ Object
Save self to the database and set the id.
-
#delete ⇒ Object
(also: #remove)
Remove self from the database and set @_id to nil.
-
#destroy ⇒ Object
Delete and freeze self.
-
#eql?(comparison_object) ⇒ Boolean
Delegate to ==.
-
#hash ⇒ Object
Delegate to id in order to allow two records of the same type and id to work with something like: [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ].
-
#id ⇒ Object
Return this object’s id.
-
#id=(val) ⇒ Object
Set the id of this object.
-
#initialize(row = {}) {|_self| ... } ⇒ Base
constructor
Initialize a new object with either a hash of values or a row returned from the database.
-
#new_record? ⇒ Boolean
Return true if this object is new—that is, does not yet have an id.
-
#save ⇒ Object
Save self and returns true if the save was successful, false if not.
-
#save! ⇒ Object
Save self and returns true if the save was successful and raises RecordNotSaved if not.
-
#to_mongo_value ⇒ Object
Convert this object to a Mongo value suitable for saving to the database.
-
#to_param ⇒ Object
Rails convenience method.
-
#update ⇒ Object
Save self to the database.
-
#update_attribute(name, value) ⇒ Object
Updates a single attribute and saves the record.
-
#update_attributes(attributes) ⇒ Object
Updates all the attributes from the passed-in Hash and saves the record.
-
#update_attributes!(attributes) ⇒ Object
Updates an object just like Base.update_attributes but calls save! instead of save so an exception is raised if the record is invalid.
Constructor Details
#initialize(row = {}) {|_self| ... } ⇒ Base
Initialize a new object with either a hash of values or a row returned from the database.
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 |
# File 'lib/mongo_record/base.rb', line 636 def initialize(row={}) case row when Hash row.each { |k, val| k = '_id' if k == 'id' # Rails helper init_ivar("@#{k}", val) } else row.instance_variables.each { |iv| init_ivar(iv, row.instance_variable_get(iv)) } end # Default values for remaining fields (self.class.field_names + self.class.subobjects.keys).each { |iv| iv = "@#{iv}" instance_variable_set(iv, nil) unless instance_variable_defined?(iv) } self.class.arrays.keys.each { |iv| iv = "@#{iv}" instance_variable_set(iv, []) unless instance_variable_defined?(iv) } yield self if block_given? end |
Class Method Details
.arrays ⇒ Object
Return the names of all instance variables that hold objects declared using has_many. The names do not start with ‘@’.
157 |
# File 'lib/mongo_record/base.rb', line 157 def arrays; @arrays; end |
.belongs_to(name, options = {}) ⇒ Object
Tells Mongo that this object belongs to another. A no-op.
205 206 |
# File 'lib/mongo_record/base.rb', line 205 def belongs_to(name, ={}) end |
.collection ⇒ Object
The collection object for this class, which will be different for every subclass of MongoRecord::Base.
210 211 212 |
# File 'lib/mongo_record/base.rb', line 210 def collection connection.collection(@coll_name.to_s) end |
.collection_name(coll_name) ⇒ Object
Call this method to set the Mongo collection name for this class. The default value is the class name turned into lower_case_with_underscores.
119 120 121 122 |
# File 'lib/mongo_record/base.rb', line 119 def collection_name(coll_name) @coll_name = coll_name field(:_id, :_ns, :_update) end |
.connection ⇒ Object
Return the database connection. The default value is # $db.
89 90 91 92 93 |
# File 'lib/mongo_record/base.rb', line 89 def connection conn = @@connection || $db raise "connection not defined" unless conn conn end |
.connection=(val) ⇒ Object
Set the database connection. If the connection is set to nil, then $db will be used.
97 98 99 100 |
# File 'lib/mongo_record/base.rb', line 97 def connection=(val) @@connection = val @@connection.pk_factory = PKFactory.new unless @@connection.pk_factory end |
.count(options = {}) ⇒ Object
Returns the number of matching records.
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
# File 'lib/mongo_record/base.rb', line 300 def count(={}) criteria = criteria_from([:conditions]).merge!(where_func([:where])) begin collection.count(criteria) rescue => ex if ex.to_s =~ /Error with count command.*ns does not exist/ # Return 0 because we will graciously assume that we are being # called from a subclass that has been initialized properly, and # is therefore mentioned in the schema. 0 else raise ex end end end |
.create(values_hash) ⇒ Object
Creates, saves, and returns a new database object.
350 351 352 353 354 |
# File 'lib/mongo_record/base.rb', line 350 def create(values_hash) object = self.new(values_hash) object.save object end |
.delete(id) ⇒ Object
Deletes the record with the given id from the collection.
317 318 319 |
# File 'lib/mongo_record/base.rb', line 317 def delete(id) collection.remove({:_id => id}) end |
.delete_all(conditions = nil) ⇒ Object
Deletes all records that match condition, which can be a Mongo-style hash or an ActiveRecord-like hash. Examples:
Person.destroy_all "name like '%fred%' # SQL WHERE clause
Person.destroy_all ["name = ?", 'Fred'] # Rails condition
Person.destroy_all {:name => 'Fred'} # Mongo hash
345 346 347 |
# File 'lib/mongo_record/base.rb', line 345 def delete_all(conditions=nil) collection.remove(criteria_from(conditions)) end |
.destroy(id) ⇒ Object
Load the object with id and delete it.
323 324 325 |
# File 'lib/mongo_record/base.rb', line 323 def destroy(id) id.is_a?(Array) ? id.each { |oid| destroy(oid) } : find(id).destroy end |
.destroy_all(conditions = nil) ⇒ Object
Destroy all objects that match conditions. Warning: if conditions is nil, all records in the collection will be destroyed.
336 337 338 |
# File 'lib/mongo_record/base.rb', line 336 def destroy_all(conditions = nil) find(:all, :conditions => conditions).each { |object| object.destroy } end |
.field(*fields) ⇒ Object Also known as: fields
Creates one or more collection fields. Each field will be saved to and loaded from the database. The fields named “_id” and “_ns” are automatically saved and loaded.
The method “field” is also called “fields”; you can use either one.
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/mongo_record/base.rb', line 129 def field(*fields) fields.each { |field| field = field.to_sym unless @field_names.include?(field) ivar_name = "@" + field.to_s define_method(field, lambda { instance_variable_get(ivar_name) }) define_method("#{field}=".to_sym, lambda { |val| instance_variable_set(ivar_name, val) }) define_method("#{field}?".to_sym, lambda { val = instance_variable_get(ivar_name) val != nil && (!val.kind_of?(String) || val != '') }) @field_names << field end } end |
.field_names ⇒ Object
Return the field names.
147 |
# File 'lib/mongo_record/base.rb', line 147 def field_names; @field_names; end |
.find(*args) ⇒ Object
Find one or more database objects.
-
Find by id (a single id or an array of ids) returns one record or a Cursor.
-
Find :first returns the first record that matches the options used or nil if not found.
-
Find :all records; returns a Cursor that can iterate over raw records.
Options:
:conditions - Hash where key is field name and value is field value. Value may be a simple value like a string, number, or regular expression.
:select - Single field name or list of field names. If not specified, all fields are returned. Names may be symbols or strings. The database always returns _id and _ns fields.
:order - If a symbol, orders by that field in ascending order. If a string like “field1 asc, field2 desc, field3”, then sorts those fields in the specified order (default is ascending). If an array, each element is either a field name or symbol (which will be sorted in ascending order) or a hash where key =isfield and value is ‘asc’ or ‘desc’ (case-insensitive), 1 or -1, or if any other value then true == 1 and false/nil == -1.
:limit - Maximum number of records to return.
:offset - Number of records to skip.
:where - A string containing a JavaScript expression. This expression is run by the database server against each record found after the :conditions are run.
Examples for find by id:
Person.find("48e5307114f4abdf00dfeb86") # returns the object for this ID
Person.find(["a_hex_id", "another_hex_id"]) # returns a Cursor over these two objects
Person.find(["a_hex_id"]) # returns a Cursor over the object with this ID
Person.find("a_hex_id", :conditions => "admin = 1", :order => "created_on DESC")
Examples for find first:
Person.find(:first) # returns the first object in the collection
Person.find(:first, :conditions => ["user_name = ?", user_name])
Person.find(:first, :order => "created_on DESC", :offset => 5)
Person.find(:first, :order => {:created_on => -1}, :offset => 5) # same as previous example
Examples for find all:
Person.find(:all) # returns a Cursor over all objects in the collection
Person.find(:all, :conditions => ["category = ?, category], :limit => 50)
Person.find(:all, :offset => 10, :limit => 10)
Person.find(:all, :select => :name) # Only returns name (and _id) fields
Find_by_*
Person.find_by_name_and_age("Spongebob", 42)
Person.find_all_by_name("Fred")
Mongo-specific example:
Person.find(:all, :where => "this.address.city == 'New York' || this.age = 42")
As a side note, the :order, :limit, and :offset options are passed on to the Cursor (after the :order option is rewritten to be a hash). So
Person.find(:all, :offset => 10, :limit => 10, :order => :created_on)
is the same as
Person.find(:all).skip(10).limit(10).sort({:created_on => 1})
281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/mongo_record/base.rb', line 281 def find(*args) = (args) case args.first when :first find_initial() when :all find_every() else find_from_ids(args, ) end end |
.find_by_mql(mql) ⇒ Object Also known as: find_by_sql
Returns all records matching mql. Not yet implemented.
294 295 296 |
# File 'lib/mongo_record/base.rb', line 294 def find_by_mql(mql) # :nodoc: raise "not implemented" end |
.has_and_belongs_to_many(name, options = {}) ⇒ Object
Tells Mongo that this object has and many belongs to another object. A no-op.
201 202 |
# File 'lib/mongo_record/base.rb', line 201 def has_and_belongs_to_many(name, ={}) end |
.has_many(name, options = {}) ⇒ Object
Tells Mongo about an array of subobjects (which need not be MongoRecord::Subobjects).
Options: :class_name - Name of the class of the subobject.
187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/mongo_record/base.rb', line 187 def has_many(name, ={}) name = name.to_sym unless @arrays[name] ivar_name = "@" + name.to_s define_method(name, lambda { instance_variable_get(ivar_name) }) define_method("#{name}=".to_sym, lambda { |val| instance_variable_set(ivar_name, val) }) define_method("#{name}?".to_sym, lambda { !instance_variable_get(ivar_name).empty? }) klass_name = [:class_name] || field_name_to_class_name(name) @arrays[name] = Kernel.const_get(klass_name) end end |
.has_one(name, options = {}) ⇒ Object
Tell Mongo about a subobject (which need not be a MongoRecord::Subobject).
Options: <code>:class_name<code> - Name of the class of the subobject.
167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/mongo_record/base.rb', line 167 def has_one(name, ={}) name = name.to_sym unless @subobjects[name] ivar_name = "@" + name.to_s define_method(name, lambda { instance_variable_get(ivar_name) }) define_method("#{name}=".to_sym, lambda { |val| instance_variable_set(ivar_name, val) }) define_method("#{name}?".to_sym, lambda { val = instance_variable_get(ivar_name) val != nil && (!val.kind_of?(String) || val != '') }) klass_name = [:class_name] || field_name_to_class_name(name) @subobjects[name] = Kernel.const_get(klass_name) end end |
.inherited(subclass) ⇒ Object
Get ready to save information about subclass.
109 110 111 112 113 114 |
# File 'lib/mongo_record/base.rb', line 109 def inherited(subclass) subclass.instance_variable_set("@coll_name", class_name_to_field_name(subclass.name)) # default name subclass.instance_variable_set("@field_names", []) # array of scalars names (symbols) subclass.instance_variable_set("@subobjects", {}) # key = name (symbol), value = class subclass.instance_variable_set("@arrays", {}) # key = name (symbol), value = class end |
.instantiate(row = {}) ⇒ Object
This method only exists so that MongoRecord::Base and ActiveRecord::Base can live side by side.
104 105 106 |
# File 'lib/mongo_record/base.rb', line 104 def instantiate(row={}) new(row) end |
.method_missing(sym, *args) ⇒ Object
Handles find_* methods such as find_by_name, find_all_by_shoe_size, and find_or_create_by_name.
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 |
# File 'lib/mongo_record/base.rb', line 381 def method_missing(sym, *args) if match = /^find_(all_by|by)_([_a-zA-Z]\w*)$/.match(sym.to_s) find_how_many = ($1 == 'all_by') ? :all : :first field_names = $2.split(/_and_/) super unless all_fields_exist?(field_names) search = search_from_names_and_values(field_names, args) self.find(find_how_many, {:conditions => search}, *args[field_names.length..-1]) elsif match = /^find_or_(initialize|create)_by_([_a-zA-Z]\w*)$/.match(sym.to_s) create = $1 == 'create' field_names = $2.split(/_and_/) super unless all_fields_exist?(field_names) search = search_from_names_and_values(field_names, args) row = self.find(:first, {:conditions => search}) return self.new(row) if row # found obj = self.new(search.merge(args[field_names.length] || {})) # new object using search and remainder of args obj.save if create obj else super end end |
.mongo_ivar_names ⇒ Object
Return the names of all fields, subobjects, and arrays.
160 |
# File 'lib/mongo_record/base.rb', line 160 def mongo_ivar_names; @field_names + @subobjects.keys + @arrays.keys; end |
.remove ⇒ Object
Deletes the record with the given id from the collection.
320 321 322 |
# File 'lib/mongo_record/base.rb', line 320 def delete(id) collection.remove({:_id => id}) end |
.subobjects ⇒ Object
Return the names of all instance variables that hold objects declared using has_one. The names do not start with ‘@’.
These are not necessarily MongoRecord::Subobject subclasses.
153 |
# File 'lib/mongo_record/base.rb', line 153 def subobjects; @subobjects; end |
.update(id, attributes) ⇒ Object
Finds the record from the passed id, instantly saves it with the passed attributes (if the validation permits it), and returns it. If the save fails under validations, the unsaved object is still returned.
The arguments may also be given as arrays in which case the update method is called for each pair of id and attributes and an array of objects is returned.
>
Example of updating one record:
Person.update(15, {:user_name => 'Samuel', :group => 'expert'})
Example of updating multiple records:
people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy"} }
Person.update(people.keys, people.values)
368 369 370 371 372 373 374 375 376 377 |
# File 'lib/mongo_record/base.rb', line 368 def update(id, attributes) if id.is_a?(Array) i = -1 id.collect { |id| i += 1; update(id, attributes[i]) } else object = find(id) object.update_attributes(attributes) object end end |
.update_all(updates, conditions = nil) ⇒ Object
Not yet implemented.
328 329 330 331 |
# File 'lib/mongo_record/base.rb', line 328 def update_all(updates, conditions = nil) # TODO raise "not yet implemented" end |
Instance Method Details
#==(comparison_object) ⇒ Object
Return true if the comparison_object is the same object, or is of the same type and has the same id.
668 669 670 671 672 673 |
# File 'lib/mongo_record/base.rb', line 668 def ==(comparison_object) comparison_object.equal?(self) || (comparison_object.instance_of?(self.class) && comparison_object.id == id && !comparison_object.new_record?) end |
#attributes_from_column_definition ⇒ Object
Does nothing.
782 |
# File 'lib/mongo_record/base.rb', line 782 def attributes_from_column_definition; end |
#create ⇒ Object
Save self to the database and set the id.
716 717 718 719 720 721 |
# File 'lib/mongo_record/base.rb', line 716 def create set_create_times with_id = self.class.collection.insert(to_mongo_value) @_id = with_id['_id'] || with_id[:_id] self end |
#delete ⇒ Object Also known as: remove
Remove self from the database and set @_id to nil. If self has no @_id, does nothing.
736 737 738 739 740 741 |
# File 'lib/mongo_record/base.rb', line 736 def delete if @_id self.class.collection.remove({:_id => self._id}) @_id = nil end end |
#destroy ⇒ Object
Delete and freeze self.
745 746 747 748 |
# File 'lib/mongo_record/base.rb', line 745 def destroy delete freeze end |
#eql?(comparison_object) ⇒ Boolean
Delegate to ==
676 677 678 |
# File 'lib/mongo_record/base.rb', line 676 def eql?(comparison_object) self == (comparison_object) end |
#hash ⇒ Object
Delegate to id in order to allow two records of the same type and id to work with something like:
[ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
682 683 684 |
# File 'lib/mongo_record/base.rb', line 682 def hash id.hash end |
#id ⇒ Object
Return this object’s id.
664 |
# File 'lib/mongo_record/base.rb', line 664 def id; @_id ? @_id.to_s : nil; end |
#id=(val) ⇒ Object
Set the id of this object. Normally not called by user code.
661 |
# File 'lib/mongo_record/base.rb', line 661 def id=(val); @_id = (val == '' ? nil : val); end |
#new_record? ⇒ Boolean
Return true if this object is new—that is, does not yet have an id.
703 704 705 |
# File 'lib/mongo_record/base.rb', line 703 def new_record? @_id == nil end |
#save ⇒ Object
Save self and returns true if the save was successful, false if not.
692 693 694 |
# File 'lib/mongo_record/base.rb', line 692 def save create_or_update end |
#save! ⇒ Object
Save self and returns true if the save was successful and raises RecordNotSaved if not.
698 699 700 |
# File 'lib/mongo_record/base.rb', line 698 def save! create_or_update || raise(RecordNotSaved) end |
#to_mongo_value ⇒ Object
Convert this object to a Mongo value suitable for saving to the database.
709 710 711 712 713 |
# File 'lib/mongo_record/base.rb', line 709 def to_mongo_value h = {} self.class.mongo_ivar_names.each {|iv| h[iv] = instance_variable_get("@#{iv}").to_mongo_value } h end |
#to_param ⇒ Object
Rails convenience method. Return this object’s id as a string.
687 688 689 |
# File 'lib/mongo_record/base.rb', line 687 def to_param @_id.to_s end |
#update ⇒ Object
Save self to the database. Return false if there was an error, self if all is well.
725 726 727 728 729 730 731 732 |
# File 'lib/mongo_record/base.rb', line 725 def update set_update_times row = self.class.collection.insert(to_mongo_value) if row['_id'].to_s != @_id.to_s return false end self end |
#update_attribute(name, value) ⇒ Object
Updates a single attribute and saves the record. This is especially useful for boolean flags on existing records. Note: This method is overwritten by the Validation module that’ll make sure that updates made with this method doesn’t get subjected to validation checks. Hence, attributes can be updated even if the full object isn’t valid.
761 762 763 764 |
# File 'lib/mongo_record/base.rb', line 761 def update_attribute(name, value) send(name.to_s + '=', value) save end |
#update_attributes(attributes) ⇒ Object
Updates all the attributes from the passed-in Hash and saves the record. If the object is invalid, the saving will fail and false will be returned.
769 770 771 772 |
# File 'lib/mongo_record/base.rb', line 769 def update_attributes(attributes) self.attributes = attributes save end |
#update_attributes!(attributes) ⇒ Object
Updates an object just like Base.update_attributes but calls save! instead of save so an exception is raised if the record is invalid.
776 777 778 779 |
# File 'lib/mongo_record/base.rb', line 776 def update_attributes!(attributes) self.attributes = attributes save! end |