Extends the model with this module after Resource has been included.
This is a useful way to extend Model while still retaining a self.extended method.
@param [Module] extensions
List of modules that will extend the model after it is extended by Model
@return [Boolean]
whether or not the inclusions have been successfully appended to the list
@api semipublic
# File lib/dm-core/model.rb, line 187 def self.append_extensions(*extensions) extra_extensions.concat extensions # Add the extension to existing descendants descendants.each do |model| extensions.each { |extension| model.extend(extension) } end true end
Appends a module for inclusion into the model class after Resource.
This is a useful way to extend Resource while still retaining a self.included method.
@param [Module] inclusions
the module that is to be appended to the module after Resource
@return [Boolean]
true if the inclusions have been successfully appended to the list
@api semipublic
# File lib/dm-core/model.rb, line 156 def self.append_inclusions(*inclusions) extra_inclusions.concat inclusions # Add the inclusion to existing descendants descendants.each do |model| inclusions.each { |inclusion| model.send :include, inclusion } end true end
Return all models that extend the Model module
class Foo include DataMapper::Resource end DataMapper::Model.descendants.first #=> Foo
@return [DescendantSet]
Set containing the descendant models
@api semipublic
# File lib/dm-core/model.rb, line 46 def self.descendants @descendants ||= DescendantSet.new end
@api private
# File lib/dm-core/model.rb, line 208 def self.extended(descendant) descendants << descendant descendant.instance_variable_set(:@valid, false) descendant.instance_variable_set(:@base_model, descendant) descendant.instance_variable_set(:@storage_names, {}) descendant.instance_variable_set(:@default_order, {}) descendant.extend(Chainable) extra_extensions.each { |mod| descendant.extend(mod) } extra_inclusions.each { |mod| descendant.send(:include, mod) } end
The current registered extra extensions
@return [Set]
@api private
# File lib/dm-core/model.rb, line 203 def self.extra_extensions @extra_extensions ||= [] end
The current registered extra inclusions
@return [Set]
@api private
# File lib/dm-core/model.rb, line 172 def self.extra_inclusions @extra_inclusions ||= [] end
Creates a new Model class with its constant already set
If a block is passed, it will be eval'd in the context of the new Model
@param [to_s] name
the name of the new model
@param [Object] namespace
the namespace that will hold the new model
@param [Proc] block
a block that will be eval'd in the context of the new Model class
@return [Model]
the newly created Model class
@api private
# File lib/dm-core/model.rb, line 23 def self.new(name = nil, namespace = Object, &block) model = name ? namespace.const_set(name, Class.new) : Class.new model.class_eval include DataMapper::Resource, __FILE__, __LINE__ + 1 model.instance_eval(&block) if block model end
Return if Resource#save should raise an exception on save failures (globally)
This is false by default.
DataMapper::Model.raise_on_save_failure # => false
@return [Boolean]
true if a failure in Resource#save should raise an exception
@api public
# File lib/dm-core/model.rb, line 79 def self.raise_on_save_failure if defined?(@raise_on_save_failure) @raise_on_save_failure else false end end
Specify if Resource#save should raise an exception on save failures (globally)
@param [Boolean]
a boolean that if true will cause Resource#save to raise an exception
@return [Boolean]
true if a failure in Resource#save should raise an exception
@api public
# File lib/dm-core/model.rb, line 96 def self.raise_on_save_failure=(raise_on_save_failure) @raise_on_save_failure = raise_on_save_failure end
# File lib/dm-core/model.rb, line 294 def [](*args) all[*args] end
Find a set of records matching an optional set of conditions. Additionally, specify the order that the records are return.
Zoo.all # all zoos Zoo.all(:open => true) # all zoos that are open Zoo.all(:opened_on => start..end) # all zoos that opened on a date in the date-range Zoo.all(:order => [ :tiger_count.desc ]) # Ordered by tiger_count
@param [Hash] query
A hash describing the conditions and order for the query
@return [Collection]
A set of records found matching the conditions in +query+
@see Collection
@api public
# File lib/dm-core/model.rb, line 336 def all(query = Undefined) if query.equal?(Undefined) || (query.kind_of?(Hash) && query.empty?) # TODO: after adding Enumerable methods to Model, try to return self here new_collection(self.query.dup) else new_collection(scoped_query(query)) end end
# File lib/dm-core/model.rb, line 300 def at(*args) all.at(*args) end
Copy a set of records from one repository to another.
@param [String] source_repository_name
The name of the Repository the resources should be copied _from_
@param [String] target_repository_name
The name of the Repository the resources should be copied _to_
@param [Hash] query
The conditions with which to find the records to copy. These conditions are merged with Model.query
@return [Collection]
A Collection of the Resource instances created in the operation
@api public
# File lib/dm-core/model.rb, line 537 def copy(source_repository_name, target_repository_name, query = {}) target_properties = properties(target_repository_name) query[:fields] ||= properties(source_repository_name).select do |property| target_properties.include?(property) end repository(target_repository_name) do |repository| resources = [] all(query.merge(:repository => source_repository_name)).each do |resource| new_resource = new query[:fields].each { |property| new_resource.__send__("#{property.name}=", property.get(resource)) } resources << new_resource if new_resource.save end all(Query.target_query(repository, self, resources)) end end
@api semipublic
# File lib/dm-core/model.rb, line 659 def default_order(repository_name = default_repository_name) @default_order[repository_name] ||= key(repository_name).map { |property| Query::Direction.new(property) }.freeze end
@api semipublic
# File lib/dm-core/model.rb, line 654 def default_repository_name Repository.default_name end
Return all models that inherit from a Model
class Foo include DataMapper::Resource end class Bar < Foo end Foo.descendants.first #=> Bar
@return [Set]
Set containing the descendant classes
@api semipublic
# File lib/dm-core/model.rb, line 65 def descendants @descendants ||= DescendantSet.new end
Remove all Resources from the repository
@return [Boolean]
true if the resources were successfully destroyed
@api public
# File lib/dm-core/model.rb, line 509 def destroy all.destroy end
Remove all Resources from the repository, bypassing validation
@return [Boolean]
true if the resources were successfully destroyed
@api public
# File lib/dm-core/model.rb, line 519 def destroy! all.destroy! end
# File lib/dm-core/model.rb, line 316 def each(&block) all.each(&block) self end
# File lib/dm-core/model.rb, line 304 def fetch(*args, &block) all.fetch(*args, &block) end
Finish model setup and verify it is valid
@return [undefined]
@api public
# File lib/dm-core/model.rb, line 136 def finalize finalize_relationships finalize_allowed_writer_methods assert_valid_name assert_valid_properties assert_valid_key end
Return the first Resource or the first N Resources for the Model with an optional query
When there are no arguments, return the first Resource in the Model. When the first argument is an Integer, return a Collection containing the first N Resources. When the last (optional) argument is a Hash scope the results to the query.
@param [Integer] limit (optional)
limit the returned Collection to a specific number of entries
@param [Hash] query (optional)
scope the returned Resource or Collection to the supplied query
@return [Resource, Collection]
The first resource in the entries of this collection, or a new collection whose query has been merged
@api public
# File lib/dm-core/model.rb, line 362 def first(*args) first_arg = args.first last_arg = args.last limit_specified = first_arg.kind_of?(Integer) with_query = (last_arg.kind_of?(Hash) && !last_arg.empty?) || last_arg.kind_of?(Query) limit = limit_specified ? first_arg : 1 query = with_query ? last_arg : {} query = self.query.slice(0, limit).update(query) if limit_specified all(query) else query.repository.read(query).first end end
Finds the first Resource by conditions, or creates a new Resource with the attributes if none found
@param [Hash] conditions
The conditions to be used to search
@param [Hash] attributes
The attributes to be used to create the record of none is found.
@return [Resource]
The instance found by +query+, or created with +attributes+ if none found
@api public
# File lib/dm-core/model.rb, line 443 def first_or_create(conditions = {}, attributes = {}) first(conditions) || create(conditions.merge(attributes)) end
Finds the first Resource by conditions, or initializes a new Resource with the attributes if none found
@param [Hash] conditions
The conditions to be used to search
@param [Hash] attributes
The attributes to be used to create the record of none is found.
@return [Resource]
The instance found by +query+, or created with +attributes+ if none found
@api public
# File lib/dm-core/model.rb, line 428 def first_or_new(conditions = {}, attributes = {}) first(conditions) || new(conditions.merge(attributes)) end
Grab a single record by its key. Supports natural and composite key lookups as well.
Zoo.get(1) # get the zoo with primary key of 1. Zoo.get!(1) # Or get! if you want an ObjectNotFoundError on failure Zoo.get('DFW') # wow, support for natural primary keys Zoo.get('Metro', 'DFW') # more wow, composite key look-up
@param [Object] *key
The primary key or keys to use for lookup
@return [Resource, nil]
A single model that was found If no instance was found matching +key+
@api public
# File lib/dm-core/model.rb, line 270 def get(*key) assert_valid_key_size(key) repository = self.repository key = self.key(repository.name).typecast(key) repository.identity_map(self)[key] || first(key_conditions(repository, key).update(:order => nil)) end
Grab a single record just like get, but raise an ObjectNotFoundError if the record doesn't exist.
@param [Object] *key
The primary key or keys to use for lookup
@return [Resource]
A single model that was found
@raise [ObjectNotFoundError]
The record was not found
@api public
# File lib/dm-core/model.rb, line 290 def get!(*key) get(*key) || raise(ObjectNotFoundError, "Could not find #{self.name} with key #{key.inspect}") end
@api private
# File lib/dm-core/model.rb, line 223 def inherited(descendant) descendants << descendant descendant.instance_variable_set(:@valid, false) descendant.instance_variable_set(:@base_model, base_model) descendant.instance_variable_set(:@storage_names, @storage_names.dup) descendant.instance_variable_set(:@default_order, @default_order.dup) end
Return the last Resource or the last N Resources for the Model with an optional query
When there are no arguments, return the last Resource for the Model. When the first argument is an Integer, return a Collection containing the last N Resources. When the last (optional) argument is a Hash scope the results to the query.
@param [Integer] limit (optional)
limit the returned Collection to a specific number of entries
@param [Hash] query (optional)
scope the returned Resource or Collection to the supplied query
@return [Resource, Collection]
The last resource in the entries of this collection, or a new collection whose query has been merged
@api public
# File lib/dm-core/model.rb, line 398 def last(*args) first_arg = args.first last_arg = args.last limit_specified = first_arg.kind_of?(Integer) with_query = (last_arg.kind_of?(Hash) && !last_arg.empty?) || last_arg.kind_of?(Query) limit = limit_specified ? first_arg : 1 query = with_query ? last_arg : {} query = self.query.slice(0, limit).update(query).reverse! if limit_specified all(query) else query.repository.read(query).last end end
Loads an instance of this Model, taking into account IdentityMap lookup, inheritance columns(s) and Property typecasting.
@param [Enumerable(Object)] records
an Array of Resource or Hashes to load a Resource with
@return [Resource]
the loaded Resource instance
@api semipublic
# File lib/dm-core/model.rb, line 567 def load(records, query) repository = query.repository repository_name = repository.name fields = query.fields discriminator = properties(repository_name).discriminator no_reload = !query.reload? field_map = Hash[ fields.map { |property| [ property, property.field ] } ] records.map do |record| identity_map = nil key_values = nil resource = nil case record when Hash # remap fields to use the Property object record = record.dup field_map.each { |property, field| record[property] = record.delete(field) if record.key?(field) } model = discriminator && discriminator.load(record[discriminator]) || self model_key = model.key(repository_name) resource = if model_key.valid?(key_values = record.values_at(*model_key)) identity_map = repository.identity_map(model) identity_map[key_values] end resource ||= model.allocate fields.each do |property| next if no_reload && property.loaded?(resource) value = record[property] # TODO: typecasting should happen inside the Adapter # and all values should come back as expected objects value = property.load(value) property.set!(resource, value) end when Resource model = record.model model_key = model.key(repository_name) resource = if model_key.valid?(key_values = record.key) identity_map = repository.identity_map(model) identity_map[key_values] end resource ||= model.allocate fields.each do |property| next if no_reload && property.loaded?(resource) property.set!(resource, property.get!(record)) end end resource.instance_variable_set(:@_repository, repository) if identity_map resource.persistence_state = Resource::PersistenceState::Clean.new(resource) unless resource.persistence_state? # defer setting the IdentityMap so second level caches can # record the state of the resource after loaded identity_map[key_values] = resource else resource.persistence_state = Resource::PersistenceState::Immutable.new(resource) end resource end end
Return if Resource#save should raise an exception on save failures (per-model)
This delegates to DataMapper::Model.raise_on_save_failure by default.
User.raise_on_save_failure # => false
@return [Boolean]
true if a failure in Resource#save should raise an exception
@api public
# File lib/dm-core/model.rb, line 110 def raise_on_save_failure if defined?(@raise_on_save_failure) @raise_on_save_failure else DataMapper::Model.raise_on_save_failure end end
Specify if Resource#save should raise an exception on save failures (per-model)
@param [Boolean]
a boolean that if true will cause Resource#save to raise an exception
@return [Boolean]
true if a failure in Resource#save should raise an exception
@api public
# File lib/dm-core/model.rb, line 127 def raise_on_save_failure=(raise_on_save_failure) @raise_on_save_failure = raise_on_save_failure end
Gets the current Set of repositories for which this Model has been defined (beyond default)
@return [Set]
The Set of repositories for which this Model has been defined (beyond default)
@api private
# File lib/dm-core/model.rb, line 708 def repositories [ repository ].to_set + @properties.keys.map { |repository_name| DataMapper.repository(repository_name) } end
Get the repository with a given name, or the default one for the current context, or the default one for this class.
@param [Symbol] name
the name of the repository wanted
@param [Block] block
block to execute with the fetched repository as parameter
@return [Object, Respository]
whatever the block returns, if given a block, otherwise the requested repository.
@api private
# File lib/dm-core/model.rb, line 676 def repository(name = nil, &block) # # There has been a couple of different strategies here, but me (zond) and dkubb are at least # united in the concept of explicitness over implicitness. That is - the explicit wish of the # caller (+name+) should be given more priority than the implicit wish of the caller (Repository.context.last). # DataMapper.repository(name || repository_name, &block) end
Get the current repository_name for this Model.
If there are any Repository contexts, the name of the last one will be returned, else the default_repository_name of this model will be
@return [String]
the current repository name to use for this Model
@api private
# File lib/dm-core/model.rb, line 695 def repository_name context = Repository.context context.any? ? context.last.name : default_repository_name end
Gets the name of the storage receptacle for this resource in the given Repository (ie., table name, for database stores).
@return [String]
the storage name (ie., table name, for database stores) associated with this resource in the given repository
@api public
# File lib/dm-core/model.rb, line 240 def storage_name(repository_name = default_repository_name) storage_names[repository_name] ||= repository(repository_name).adapter.resource_naming_convention.call(default_storage_name).freeze end
the names of the storage receptacles for this resource across all repositories
@return [Hash(Symbol => String)]
All available names of storage receptacles
@api public
# File lib/dm-core/model.rb, line 250 def storage_names @storage_names end
Update every Resource
Person.update(:allow_beer => true)
@param [Hash] attributes
attributes to update with
@return [Boolean]
true if the resources were successfully updated
@api public
# File lib/dm-core/model.rb, line 484 def update(attributes) all.update(attributes) end
Update every Resource, bypassing validations
Person.update!(:allow_beer => true)
@param [Hash] attributes
attributes to update with
@return [Boolean]
true if the resources were successfully updated
@api public
# File lib/dm-core/model.rb, line 499 def update!(attributes) all.update!(attributes) end
Generated with the Darkfish Rdoc Generator 2.