mirror of
https://github.com/github/rails.git
synced 2026-04-26 03:00:59 -04:00
Document Active Record exceptions. Closes #10444.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@8362 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
@@ -1,3 +1,8 @@
|
||||
*SVN*
|
||||
|
||||
* Document Active Record exceptions. #10444 [Michael Klishin]
|
||||
|
||||
|
||||
*2.0.1* (December 7th, 2007)
|
||||
|
||||
* Removed query cache rescue as it could cause code to be run twice (closes #10408) [DHH]
|
||||
|
||||
@@ -3,37 +3,98 @@ require 'yaml'
|
||||
require 'set'
|
||||
|
||||
module ActiveRecord #:nodoc:
|
||||
class ActiveRecordError < StandardError #:nodoc:
|
||||
# Generic ActiveRecord exception class.
|
||||
class ActiveRecordError < StandardError
|
||||
end
|
||||
|
||||
# Raised when the single-table inheritance mechanism failes to locate the subclass
|
||||
# (for example due to improper usage of column that +inheritance_column+ points to).
|
||||
class SubclassNotFound < ActiveRecordError #:nodoc:
|
||||
end
|
||||
class AssociationTypeMismatch < ActiveRecordError #:nodoc:
|
||||
|
||||
# Raised when object assigned to association is of incorrect type.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# class Ticket < ActiveRecord::Base
|
||||
# has_many :patches
|
||||
# end
|
||||
#
|
||||
# class Patch < ActiveRecord::Base
|
||||
# belongs_to :ticket
|
||||
# end
|
||||
#
|
||||
# and somewhere in the code:
|
||||
#
|
||||
# @ticket.patches << Comment.new(:content => "Please attach tests to your patch.")
|
||||
# @ticket.save
|
||||
class AssociationTypeMismatch < ActiveRecordError
|
||||
end
|
||||
class SerializationTypeMismatch < ActiveRecordError #:nodoc:
|
||||
|
||||
# Raised when unserialized object's type mismatches one specified for serializable field.
|
||||
class SerializationTypeMismatch < ActiveRecordError
|
||||
end
|
||||
class AdapterNotSpecified < ActiveRecordError # :nodoc:
|
||||
|
||||
# Raised when adapter not specified on connection (or configuration file config/database.yml misses adapter field).
|
||||
class AdapterNotSpecified < ActiveRecordError
|
||||
end
|
||||
class AdapterNotFound < ActiveRecordError # :nodoc:
|
||||
|
||||
# Raised when ActiveRecord cannot find database adapter specified in config/database.yml or programmatically.
|
||||
class AdapterNotFound < ActiveRecordError
|
||||
end
|
||||
class ConnectionNotEstablished < ActiveRecordError #:nodoc:
|
||||
|
||||
# Raised when connection to the database could not been established (for example when connection= is given a nil object).
|
||||
class ConnectionNotEstablished < ActiveRecordError
|
||||
end
|
||||
class RecordNotFound < ActiveRecordError #:nodoc:
|
||||
|
||||
# Raised when ActiveRecord cannot find record by given id or set of ids.
|
||||
class RecordNotFound < ActiveRecordError
|
||||
end
|
||||
class RecordNotSaved < ActiveRecordError #:nodoc:
|
||||
|
||||
# Raised by ActiveRecord::Base.save! and ActiveRecord::Base.create! methods when record cannot be
|
||||
# saved because record is invalid.
|
||||
class RecordNotSaved < ActiveRecordError
|
||||
end
|
||||
class StatementInvalid < ActiveRecordError #:nodoc:
|
||||
|
||||
# Raised when SQL statement cannot be executed by the database (for example, it's often the case for MySQL when Ruby driver used is too old).
|
||||
class StatementInvalid < ActiveRecordError
|
||||
end
|
||||
class PreparedStatementInvalid < ActiveRecordError #:nodoc:
|
||||
|
||||
# Raised when number of bind variables in statement given to :condition key (for example, when using +find+ method)
|
||||
# does not match number of expected variables.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# Location.find :all, :conditions => ["lat = ? AND lng = ?", 53.7362]
|
||||
#
|
||||
# in example above two placeholders are given but only one variable to fill them.
|
||||
class PreparedStatementInvalid < ActiveRecordError
|
||||
end
|
||||
class StaleObjectError < ActiveRecordError #:nodoc:
|
||||
|
||||
# Raised on attempt to save stale record. Record is stale when it's being saved in another query after
|
||||
# instantiation, for example, when two users edit the same wiki page and one starts editing and saves
|
||||
# the page before the other.
|
||||
#
|
||||
# Read more about optimistic locking in +ActiveRecord::Locking+ module RDoc.
|
||||
class StaleObjectError < ActiveRecordError
|
||||
end
|
||||
class ConfigurationError < ActiveRecordError #:nodoc:
|
||||
|
||||
# Raised when association is being configured improperly or
|
||||
# user tries to use offset and limit together with has_many or has_and_belongs_to_many associations.
|
||||
class ConfigurationError < ActiveRecordError
|
||||
end
|
||||
class ReadOnlyRecord < ActiveRecordError #:nodoc:
|
||||
|
||||
# Raised on attempt to update record that is instantiated as read only.
|
||||
class ReadOnlyRecord < ActiveRecordError
|
||||
end
|
||||
class Rollback < ActiveRecordError #:nodoc:
|
||||
|
||||
# Used by ActiveRecord transaction mechanism to distinguish rollback from other exceptional situations.
|
||||
# You can use it to roll your transaction back explicitly in the block passed to +transaction+ method.
|
||||
class Rollback < ActiveRecordError
|
||||
end
|
||||
class DangerousAttributeError < ActiveRecordError #:nodoc:
|
||||
|
||||
# Raised when attribute has a name reserved by ActiveRecord (when attribute has name of one of ActiveRecord instance methods).
|
||||
class DangerousAttributeError < ActiveRecordError
|
||||
end
|
||||
|
||||
# Raised when you've tried to access a column which wasn't
|
||||
@@ -109,7 +170,7 @@ module ActiveRecord #:nodoc:
|
||||
#
|
||||
# The <tt>authenticate_unsafely</tt> method inserts the parameters directly into the query and is thus susceptible to SQL-injection
|
||||
# attacks if the <tt>user_name</tt> and +password+ parameters come directly from an HTTP request. The <tt>authenticate_safely</tt> and
|
||||
# <tt>authenticate_safely_simply</tt> both will sanitize the <tt>user_name</tt> and +password+ before inserting them in the query,
|
||||
# <tt>authenticate_safely_simply</tt> both will sanitize the <tt>user_name</tt> and +password+ before inserting them in the query,
|
||||
# which will ensure that an attacker can't escape the query and fake the login (or worse).
|
||||
#
|
||||
# When using multiple parameters in the conditions, it can easily become hard to read exactly what the fourth or fifth
|
||||
@@ -157,7 +218,7 @@ module ActiveRecord #:nodoc:
|
||||
#
|
||||
# In addition to the basic accessors, query methods are also automatically available on the Active Record object.
|
||||
# Query methods allow you to test whether an attribute value is present.
|
||||
#
|
||||
#
|
||||
# For example, an Active Record User with the <tt>name</tt> attribute has a <tt>name?</tt> method that you can call
|
||||
# to determine whether the user has a name:
|
||||
#
|
||||
@@ -199,7 +260,7 @@ module ActiveRecord #:nodoc:
|
||||
#
|
||||
# # No 'Summer' tag exists
|
||||
# Tag.find_or_create_by_name("Summer") # equal to Tag.create(:name => "Summer")
|
||||
#
|
||||
#
|
||||
# # Now the 'Summer' tag does exist
|
||||
# Tag.find_or_create_by_name("Summer") # equal to Tag.find_by_name("Summer")
|
||||
#
|
||||
@@ -362,7 +423,7 @@ module ActiveRecord #:nodoc:
|
||||
|
||||
# Specifies the format to use when dumping the database schema with Rails'
|
||||
# Rakefile. If :sql, the schema is dumped as (potentially database-
|
||||
# specific) SQL statements. If :ruby, the schema is dumped as an
|
||||
# specific) SQL statements. If :ruby, the schema is dumped as an
|
||||
# ActiveRecord::Schema file which can be loaded into any database that
|
||||
# supports migrations. Use :ruby if you want to have different database
|
||||
# adapters for, e.g., your development and test environments.
|
||||
@@ -395,7 +456,7 @@ module ActiveRecord #:nodoc:
|
||||
# * <tt>:select</tt>: By default, this is * as in SELECT * FROM, but can be changed if you, for example, want to do a join but not
|
||||
# include the joined columns.
|
||||
# * <tt>:from</tt>: By default, this is the table name of the class, but can be changed to an alternate table name (or even the name
|
||||
# of a database view).
|
||||
# of a database view).
|
||||
# * <tt>:readonly</tt>: Mark the returned records read-only so they cannot be saved or updated.
|
||||
# * <tt>:lock</tt>: An SQL fragment like "FOR UPDATE" or "LOCK IN SHARE MODE".
|
||||
# :lock => true gives connection's default exclusive lock, usually "FOR UPDATE".
|
||||
@@ -444,20 +505,20 @@ module ActiveRecord #:nodoc:
|
||||
else find_from_ids(args, options)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Executes a custom sql query against your database and returns all the results. The results will
|
||||
# be returned as an array with columns requested encapsulated as attributes of the model you call
|
||||
# this method from. If you call +Product.find_by_sql+ then the results will be returned in a Product
|
||||
# Executes a custom sql query against your database and returns all the results. The results will
|
||||
# be returned as an array with columns requested encapsulated as attributes of the model you call
|
||||
# this method from. If you call +Product.find_by_sql+ then the results will be returned in a Product
|
||||
# object with the attributes you specified in the SQL query.
|
||||
#
|
||||
# If you call a complicated SQL query which spans multiple tables the columns specified by the
|
||||
# SELECT will be attributes of the model, whether or not they are columns of the corresponding
|
||||
# If you call a complicated SQL query which spans multiple tables the columns specified by the
|
||||
# SELECT will be attributes of the model, whether or not they are columns of the corresponding
|
||||
# table.
|
||||
#
|
||||
# The +sql+ parameter is a full sql query as a string. It will be called as is, there will be
|
||||
# no database agnostic conversions performed. This should be a last resort because using, for example,
|
||||
# MySQL specific terms will lock you to using that particular database engine or require you to
|
||||
# The +sql+ parameter is a full sql query as a string. It will be called as is, there will be
|
||||
# no database agnostic conversions performed. This should be a last resort because using, for example,
|
||||
# MySQL specific terms will lock you to using that particular database engine or require you to
|
||||
# change your call if you switch engines
|
||||
#
|
||||
# ==== Examples
|
||||
@@ -472,15 +533,15 @@ module ActiveRecord #:nodoc:
|
||||
connection.select_all(sanitize_sql(sql), "#{name} Load").collect! { |record| instantiate(record) }
|
||||
end
|
||||
|
||||
# Checks whether a record exists in the database that matches conditions given. These conditions
|
||||
# can either be a single integer representing a primary key id to be found, or a condition to be
|
||||
# Checks whether a record exists in the database that matches conditions given. These conditions
|
||||
# can either be a single integer representing a primary key id to be found, or a condition to be
|
||||
# matched like using ActiveRecord#find.
|
||||
#
|
||||
# The +id_or_conditions+ parameter can be an Integer or a String if you want to search the primary key
|
||||
# column of the table for a matching id, or if you're looking to match against a condition you can use
|
||||
# The +id_or_conditions+ parameter can be an Integer or a String if you want to search the primary key
|
||||
# column of the table for a matching id, or if you're looking to match against a condition you can use
|
||||
# an Array or a Hash.
|
||||
#
|
||||
# Possible gotcha: You can't pass in a condition as a string e.g. "name = 'Jamie'", this would be
|
||||
# Possible gotcha: You can't pass in a condition as a string e.g. "name = 'Jamie'", this would be
|
||||
# sanitized and then queried against the primary key column as "id = 'name = \'Jamie"
|
||||
#
|
||||
# ==== Examples
|
||||
@@ -494,7 +555,7 @@ module ActiveRecord #:nodoc:
|
||||
false
|
||||
end
|
||||
|
||||
# Creates an object (or multiple objects) and saves it to the database, if validations pass.
|
||||
# Creates an object (or multiple objects) and saves it to the database, if validations pass.
|
||||
# The resulting object is returned whether the object was saved successfully to the database or not.
|
||||
#
|
||||
# The +attributes+ parameter can be either be a Hash or an Array of Hashes. These Hashes describe the
|
||||
@@ -527,9 +588,9 @@ module ActiveRecord #:nodoc:
|
||||
#
|
||||
# # Updating one record:
|
||||
# Person.update(15, {:user_name => 'Samuel', :group => 'expert'})
|
||||
#
|
||||
#
|
||||
# # Updating multiple records:
|
||||
# people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy"} }
|
||||
# people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy"} }
|
||||
# Person.update(people.keys, people.values)
|
||||
def update(id, attributes)
|
||||
if id.is_a?(Array)
|
||||
@@ -545,18 +606,18 @@ module ActiveRecord #:nodoc:
|
||||
# Delete an object (or multiple objects) where the +id+ given matches the primary_key. A SQL +DELETE+ command
|
||||
# is executed on the database which means that no callbacks are fired off running this. This is an efficient method
|
||||
# of deleting records that don't need cleaning up after or other actions to be taken.
|
||||
#
|
||||
#
|
||||
# Objects are _not_ instantiated with this method.
|
||||
#
|
||||
# ==== Options
|
||||
#
|
||||
#
|
||||
# +id+ Can be either an Integer or an Array of Integers
|
||||
#
|
||||
# ==== Examples
|
||||
#
|
||||
# # Delete a single object
|
||||
# Todo.delete(1)
|
||||
#
|
||||
#
|
||||
# # Delete multiple objects
|
||||
# todos = [1,2,3]
|
||||
# Todo.delete(todos)
|
||||
@@ -567,19 +628,19 @@ module ActiveRecord #:nodoc:
|
||||
# Destroy an object (or multiple objects) that has the given id, the object is instantiated first,
|
||||
# therefore all callbacks and filters are fired off before the object is deleted. This method is
|
||||
# less efficient than ActiveRecord#delete but allows cleanup methods and other actions to be run.
|
||||
#
|
||||
# This essentially finds the object (or multiple objects) with the given id, creates a new object
|
||||
#
|
||||
# This essentially finds the object (or multiple objects) with the given id, creates a new object
|
||||
# from the attributes, and then calls destroy on it.
|
||||
#
|
||||
# ==== Options
|
||||
#
|
||||
#
|
||||
# +id+ Can be either an Integer or an Array of Integers
|
||||
#
|
||||
# ==== Examples
|
||||
#
|
||||
# # Destroy a single object
|
||||
# Todo.destroy(1)
|
||||
#
|
||||
#
|
||||
# # Destroy multiple objects
|
||||
# todos = [1,2,3]
|
||||
# Todo.destroy(todos)
|
||||
@@ -593,7 +654,7 @@ module ActiveRecord #:nodoc:
|
||||
# ==== Options
|
||||
#
|
||||
# +updates+ A String of column and value pairs that will be set on any records that match conditions
|
||||
# +conditions+ An SQL fragment like "administrator = 1" or [ "user_name = ?", username ].
|
||||
# +conditions+ An SQL fragment like "administrator = 1" or [ "user_name = ?", username ].
|
||||
# See conditions in the intro for more info.
|
||||
# +options+ Additional options are :limit and/or :order, see the examples for usage.
|
||||
#
|
||||
@@ -601,12 +662,12 @@ module ActiveRecord #:nodoc:
|
||||
#
|
||||
# # Update all billing objects with the 3 different attributes given
|
||||
# Billing.update_all( "category = 'authorized', approved = 1, author = 'David'" )
|
||||
#
|
||||
#
|
||||
# # Update records that match our conditions
|
||||
# Billing.update_all( "author = 'David'", "title LIKE '%Rails%'" )
|
||||
#
|
||||
# # Update records that match our conditions but limit it to 5 ordered by date
|
||||
# Billing.update_all( "author = 'David'", "title LIKE '%Rails%'",
|
||||
# Billing.update_all( "author = 'David'", "title LIKE '%Rails%'",
|
||||
# :order => 'created_at', :limit => 5 )
|
||||
def update_all(updates, conditions = nil, options = {})
|
||||
sql = "UPDATE #{table_name} SET #{sanitize_sql_for_assignment(updates)} "
|
||||
@@ -634,11 +695,11 @@ module ActiveRecord #:nodoc:
|
||||
end
|
||||
|
||||
# Returns the result of an SQL statement that should only include a COUNT(*) in the SELECT part.
|
||||
# The use of this method should be restricted to complicated SQL queries that can't be executed
|
||||
# The use of this method should be restricted to complicated SQL queries that can't be executed
|
||||
# using the ActiveRecord::Calculations class methods. Look into those before using this.
|
||||
#
|
||||
# ==== Options
|
||||
#
|
||||
#
|
||||
# +sql+: An SQL statement which should return a count query from the database, see the example below
|
||||
#
|
||||
# ==== Examples
|
||||
@@ -656,15 +717,15 @@ module ActiveRecord #:nodoc:
|
||||
# given by the corresponding value:
|
||||
#
|
||||
# ==== Options
|
||||
#
|
||||
#
|
||||
# +id+ The id of the object you wish to update a counter on
|
||||
# +counters+ An Array of Hashes containing the names of the fields
|
||||
# +counters+ An Array of Hashes containing the names of the fields
|
||||
# to update as keys and the amount to update the field by as
|
||||
# values
|
||||
#
|
||||
#
|
||||
# ==== Examples
|
||||
#
|
||||
# # For the Post with id of 5, decrement the comment_count by 1, and
|
||||
#
|
||||
# # For the Post with id of 5, decrement the comment_count by 1, and
|
||||
# # increment the action_count by 1
|
||||
# Post.update_counters 5, :comment_count => -1, :action_count => 1
|
||||
# # Executes the following SQL:
|
||||
@@ -682,8 +743,8 @@ module ActiveRecord #:nodoc:
|
||||
|
||||
# Increment a number field by one, usually representing a count.
|
||||
#
|
||||
# This is used for caching aggregate values, so that they don't need to be computed every time.
|
||||
# For example, a DiscussionBoard may cache post_count and comment_count otherwise every time the board is
|
||||
# This is used for caching aggregate values, so that they don't need to be computed every time.
|
||||
# For example, a DiscussionBoard may cache post_count and comment_count otherwise every time the board is
|
||||
# shown it would have to run an SQL query to find how many posts and comments there are.
|
||||
#
|
||||
# ==== Options
|
||||
@@ -743,14 +804,14 @@ module ActiveRecord #:nodoc:
|
||||
read_inheritable_attribute("attr_protected")
|
||||
end
|
||||
|
||||
# Similar to the attr_protected macro, this protects attributes of your model from mass-assignment,
|
||||
# Similar to the attr_protected macro, this protects attributes of your model from mass-assignment,
|
||||
# such as <tt>new(attributes)</tt> and <tt>attributes=(attributes)</tt>
|
||||
# however, it does it in the opposite way. This locks all attributes and only allows access to the
|
||||
# attributes specified. Assignment to attributes not in this list will be ignored and need to be set
|
||||
# using the direct writer methods instead. This is meant to protect sensitive attributes from being
|
||||
# overwritten by URL/form hackers. If you'd rather start from an all-open default and restrict
|
||||
# however, it does it in the opposite way. This locks all attributes and only allows access to the
|
||||
# attributes specified. Assignment to attributes not in this list will be ignored and need to be set
|
||||
# using the direct writer methods instead. This is meant to protect sensitive attributes from being
|
||||
# overwritten by URL/form hackers. If you'd rather start from an all-open default and restrict
|
||||
# attributes as needed, have a look at attr_protected.
|
||||
#
|
||||
#
|
||||
# ==== Options
|
||||
#
|
||||
# <tt>*attributes</tt> A comma separated list of symbols that represent columns _not_ to be protected
|
||||
@@ -787,9 +848,9 @@ module ActiveRecord #:nodoc:
|
||||
read_inheritable_attribute("attr_readonly")
|
||||
end
|
||||
|
||||
# If you have an attribute that needs to be saved to the database as an object, and retrieved as the same object,
|
||||
# then specify the name of that attribute using this method and it will be handled automatically.
|
||||
# The serialization is done through YAML. If +class_name+ is specified, the serialized object must be of that
|
||||
# If you have an attribute that needs to be saved to the database as an object, and retrieved as the same object,
|
||||
# then specify the name of that attribute using this method and it will be handled automatically.
|
||||
# The serialization is done through YAML. If +class_name+ is specified, the serialized object must be of that
|
||||
# class on retrieval or +SerializationTypeMismatch+ will be raised.
|
||||
#
|
||||
# ==== Options
|
||||
@@ -988,7 +1049,7 @@ module ActiveRecord #:nodoc:
|
||||
columns.size > 0
|
||||
rescue ActiveRecord::StatementInvalid
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1121,7 +1182,7 @@ module ActiveRecord #:nodoc:
|
||||
# Overwrite the default class equality method to provide support for association proxies.
|
||||
def ===(object)
|
||||
object.is_a?(self)
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the base AR subclass that this class descends from. If A
|
||||
# extends AR::Base, A.base_class will return A. If B descends from A
|
||||
@@ -1147,7 +1208,7 @@ module ActiveRecord #:nodoc:
|
||||
|
||||
def find_every(options)
|
||||
records = scoped?(:find, :include) || options[:include] ?
|
||||
find_with_associations(options) :
|
||||
find_with_associations(options) :
|
||||
find_by_sql(construct_finder_sql(options))
|
||||
|
||||
records.each { |record| record.readonly! } if options[:readonly]
|
||||
@@ -1171,7 +1232,7 @@ module ActiveRecord #:nodoc:
|
||||
find_some(ids, options)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def find_one(id, options)
|
||||
conditions = " AND (#{sanitize_sql(options[:conditions])})" if options[:conditions]
|
||||
options.update :conditions => "#{quoted_table_name}.#{connection.quote_column_name(primary_key)} = #{quote_value(id,columns_hash[primary_key])}#{conditions}"
|
||||
@@ -1185,7 +1246,7 @@ module ActiveRecord #:nodoc:
|
||||
raise RecordNotFound, "Couldn't find #{name} with ID=#{id}#{conditions}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def find_some(ids, options)
|
||||
conditions = " AND (#{sanitize_sql(options[:conditions])})" if options[:conditions]
|
||||
ids_list = ids.map { |id| quote_value(id,columns_hash[primary_key]) }.join(',')
|
||||
@@ -1388,7 +1449,7 @@ module ActiveRecord #:nodoc:
|
||||
# It's even possible to use all the additional parameters to find. For example, the full interface for find_all_by_amount
|
||||
# is actually find_all_by_amount(amount, options).
|
||||
#
|
||||
# This also enables you to initialize a record if it is not found, such as find_or_initialize_by_amount(amount)
|
||||
# This also enables you to initialize a record if it is not found, such as find_or_initialize_by_amount(amount)
|
||||
# or find_or_create_by_user_and_password(user, password).
|
||||
#
|
||||
# Each dynamic finder or initializer/creator is also defined in the class after it is first invoked, so that future
|
||||
@@ -1401,7 +1462,7 @@ module ActiveRecord #:nodoc:
|
||||
super unless all_attributes_exists?(attribute_names)
|
||||
|
||||
self.class_eval %{
|
||||
def self.#{method_id}(*args)
|
||||
def self.#{method_id}(*args)
|
||||
options = args.last.is_a?(Hash) ? args.pop : {}
|
||||
attributes = construct_attributes_from_arguments([:#{attribute_names.join(',:')}], args)
|
||||
finder_options = { :conditions => attributes }
|
||||
@@ -1424,24 +1485,24 @@ module ActiveRecord #:nodoc:
|
||||
super unless all_attributes_exists?(attribute_names)
|
||||
|
||||
self.class_eval %{
|
||||
def self.#{method_id}(*args)
|
||||
def self.#{method_id}(*args)
|
||||
if args[0].is_a?(Hash)
|
||||
attributes = args[0].with_indifferent_access
|
||||
find_attributes = attributes.slice(*[:#{attribute_names.join(',:')}])
|
||||
else
|
||||
find_attributes = attributes = construct_attributes_from_arguments([:#{attribute_names.join(',:')}], args)
|
||||
end
|
||||
|
||||
|
||||
options = { :conditions => find_attributes }
|
||||
set_readonly_option!(options)
|
||||
|
||||
record = find_initial(options)
|
||||
if record.nil?
|
||||
record = self.new { |r| r.send(:attributes=, attributes, false) }
|
||||
record = self.new { |r| r.send(:attributes=, attributes, false) }
|
||||
#{'record.save' if instantiator == :create}
|
||||
record
|
||||
else
|
||||
record
|
||||
record
|
||||
end
|
||||
end
|
||||
}, __FILE__, __LINE__
|
||||
@@ -1471,7 +1532,7 @@ module ActiveRecord #:nodoc:
|
||||
|
||||
def all_attributes_exists?(attribute_names)
|
||||
attribute_names.all? { |name| column_methods_hash.include?(name.to_sym) }
|
||||
end
|
||||
end
|
||||
|
||||
def attribute_condition(argument)
|
||||
case argument
|
||||
@@ -1642,18 +1703,18 @@ module ActiveRecord #:nodoc:
|
||||
scoped_methods = (Thread.current[:scoped_methods] ||= {})
|
||||
scoped_methods[self] ||= []
|
||||
end
|
||||
|
||||
|
||||
def single_threaded_scoped_methods #:nodoc:
|
||||
@scoped_methods ||= []
|
||||
end
|
||||
|
||||
|
||||
# pick up the correct scoped_methods version from @@allow_concurrency
|
||||
if @@allow_concurrency
|
||||
alias_method :scoped_methods, :thread_safe_scoped_methods
|
||||
else
|
||||
alias_method :scoped_methods, :single_threaded_scoped_methods
|
||||
end
|
||||
|
||||
|
||||
def current_scoped_methods #:nodoc:
|
||||
scoped_methods.last
|
||||
end
|
||||
@@ -1826,8 +1887,8 @@ module ActiveRecord #:nodoc:
|
||||
|
||||
def encode_quoted_value(value) #:nodoc:
|
||||
quoted_value = connection.quote(value)
|
||||
quoted_value = "'#{quoted_value[1..-2].gsub(/\'/, "\\\\'")}'" if quoted_value.include?("\\\'") # (for ruby mode) "
|
||||
quoted_value
|
||||
quoted_value = "'#{quoted_value[1..-2].gsub(/\'/, "\\\\'")}'" if quoted_value.include?("\\\'") # (for ruby mode) "
|
||||
quoted_value
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1853,7 +1914,7 @@ module ActiveRecord #:nodoc:
|
||||
def id
|
||||
attr_name = self.class.primary_key
|
||||
column = column_for_attribute(attr_name)
|
||||
|
||||
|
||||
self.class.send(:define_read_method, :id, attr_name, column)
|
||||
# now that the method exists, call it
|
||||
self.send attr_name.to_sym
|
||||
@@ -1889,8 +1950,8 @@ module ActiveRecord #:nodoc:
|
||||
def save
|
||||
create_or_update
|
||||
end
|
||||
|
||||
# Attempts to save the record, but instead of just returning false if it couldn't happen, it raises a
|
||||
|
||||
# Attempts to save the record, but instead of just returning false if it couldn't happen, it raises a
|
||||
# RecordNotSaved exception
|
||||
def save!
|
||||
create_or_update || raise(RecordNotSaved)
|
||||
@@ -1951,7 +2012,7 @@ module ActiveRecord #:nodoc:
|
||||
self.attributes = attributes
|
||||
save
|
||||
end
|
||||
|
||||
|
||||
# Updates an object just like Base.update_attributes but calls save! instead of save so an exception is raised if the record is invalid.
|
||||
def update_attributes!(attributes)
|
||||
self.attributes = attributes
|
||||
@@ -2022,7 +2083,7 @@ module ActiveRecord #:nodoc:
|
||||
# matching the attribute names (which again matches the column names). Sensitive attributes can be protected
|
||||
# from this form of mass-assignment by using the +attr_protected+ macro. Or you can alternatively
|
||||
# specify which attributes *can* be accessed with the +attr_accessible+ macro. Then all the
|
||||
# attributes not included in that won't be allowed to be mass-assigned.
|
||||
# attributes not included in that won't be allowed to be mass-assigned.
|
||||
def attributes=(new_attributes, guard_protected_attributes = true)
|
||||
return if new_attributes.nil?
|
||||
attributes = new_attributes.dup
|
||||
@@ -2030,7 +2091,7 @@ module ActiveRecord #:nodoc:
|
||||
|
||||
multi_parameter_attributes = []
|
||||
attributes = remove_attributes_protected_from_mass_assignment(attributes) if guard_protected_attributes
|
||||
|
||||
|
||||
attributes.each do |k, v|
|
||||
k.include?("(") ? multi_parameter_attributes << [ k, v ] : send(k + "=", v)
|
||||
end
|
||||
@@ -2042,7 +2103,7 @@ module ActiveRecord #:nodoc:
|
||||
# Returns a hash of all the attributes with their names as keys and clones of their objects as values.
|
||||
def attributes(options = nil)
|
||||
attributes = clone_attributes :read_attribute
|
||||
|
||||
|
||||
if options.nil?
|
||||
attributes
|
||||
else
|
||||
@@ -2103,8 +2164,8 @@ module ActiveRecord #:nodoc:
|
||||
# Returns true if the +comparison_object+ is the same object, or is of the same type and has the same id.
|
||||
def ==(comparison_object)
|
||||
comparison_object.equal?(self) ||
|
||||
(comparison_object.instance_of?(self.class) &&
|
||||
comparison_object.id == id &&
|
||||
(comparison_object.instance_of?(self.class) &&
|
||||
comparison_object.id == id &&
|
||||
!comparison_object.new_record?)
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user