Class: ActiveRecord::Base

Active Record objects don‘t specify their attributes directly, but rather infer them from the table definition with which they‘re linked. Adding, removing, and changing attributes and their type is done directly in the database. Any change is instantly reflected in the Active Record objects. The mapping that binds a given Active Record class to a certain database table will happen automatically in most common cases, but can be overwritten for the uncommon ones.

See the mapping rules in table_name and the full example in files/README.html for more insight.

Creation

Active Records accept constructor parameters either in a hash or as a block. The hash method is especially useful when you‘re receiving the data from somewhere else, like an HTTP request. It works like this:

  user = User.new(:name => "David", :occupation => "Code Artist")
  user.name # => "David"

You can also use block initialization:

  user = User.new do |u|
    u.name = "David"
    u.occupation = "Code Artist"
  end

And of course you can just create a bare object and specify the attributes after the fact:

  user = User.new
  user.name = "David"
  user.occupation = "Code Artist"

Conditions

Conditions can either be specified as a string, array, or hash representing the WHERE-part of an SQL statement. The array form is to be used when the condition input is tainted and requires sanitization. The string form can be used for statements that don‘t involve tainted data. The hash form works much like the array form, except only equality and range is possible. Examples:

  class User < ActiveRecord::Base
    def self.authenticate_unsafely(user_name, password)
      find(:first, :conditions => "user_name = '#{user_name}' AND password = '#{password}'")
    end

    def self.authenticate_safely(user_name, password)
      find(:first, :conditions => [ "user_name = ? AND password = ?", user_name, password ])
    end

    def self.authenticate_safely_simply(user_name, password)
      find(:first, :conditions => { :user_name => user_name, :password => password })
    end
  end

The authenticate_unsafely method inserts the parameters directly into the query and is thus susceptible to SQL-injection attacks if the user_name and password parameters come directly from an HTTP request. The authenticate_safely and authenticate_safely_simply both will sanitize the user_name 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 question mark is supposed to represent. In those cases, you can resort to named bind variables instead. That‘s done by replacing the question marks with symbols and supplying a hash with values for the matching symbol keys:

  Company.find(:first, :conditions => [
    "id = :id AND name = :name AND division = :division AND created_at > :accounting_date",
    { :id => 3, :name => "37signals", :division => "First", :accounting_date => '2005-01-01' }
  ])

Similarly, a simple hash without a statement will generate conditions based on equality with the SQL AND operator. For instance:

  Student.find(:all, :conditions => { :first_name => "Harvey", :status => 1 })
  Student.find(:all, :conditions => params[:student])

A range may be used in the hash to use the SQL BETWEEN operator:

  Student.find(:all, :conditions => { :grade => 9..12 })

Overwriting default accessors

All column values are automatically available through basic accessors on the Active Record object, but sometimes you want to specialize this behavior. This can be done by overwriting the default accessors (using the same name as the attribute) and calling read_attribute(attr_name) and write_attribute(attr_name, value) to actually change things. Example:

  class Song < ActiveRecord::Base
    # Uses an integer of seconds to hold the length of the song

    def length=(minutes)
      write_attribute(:length, minutes * 60)
    end

    def length
      read_attribute(:length) / 60
    end
  end

You can alternatively use self[:attribute]=(value) and self[:attribute] instead of write_attribute(:attribute, value) and read_attribute(:attribute) as a shorter form.

Attribute query methods

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 name attribute has a name? method that you can call to determine whether the user has a name:

  user = User.new(:name => "David")
  user.name? # => true

  anonymous = User.new(:name => "")
  anonymous.name? # => false

Accessing attributes before they have been typecasted

Sometimes you want to be able to read the raw attribute data without having the column-determined typecast run its course first. That can be done by using the <attribute>_before_type_cast accessors that all attributes have. For example, if your Account model has a balance attribute, you can call account.balance_before_type_cast or account.id_before_type_cast.

This is especially useful in validation situations where the user might supply a string for an integer field and you want to display the original string back in an error message. Accessing the attribute normally would typecast the string to 0, which isn‘t what you want.

Dynamic attribute-based finders

Dynamic attribute-based finders are a cleaner way of getting (and/or creating) objects by simple queries without turning to SQL. They work by appending the name of an attribute to find_by_ or find_all_by_, so you get finders like Person.find_by_user_name, Person.find_all_by_last_name, Payment.find_by_transaction_id. So instead of writing Person.find(:first, :conditions => ["user_name = ?", user_name]), you just do Person.find_by_user_name(user_name). And instead of writing Person.find(:all, :conditions => ["last_name = ?", last_name]), you just do Person.find_all_by_last_name(last_name).

It‘s also possible to use multiple attributes in the same find by separating them with "and", so you get finders like Person.find_by_user_name_and_password or even Payment.find_by_purchaser_and_state_and_country. So instead of writing Person.find(:first, :conditions => ["user_name = ? AND password = ?", user_name, password]), you just do Person.find_by_user_name_and_password(user_name, password).

It‘s even possible to use all the additional parameters to find. For example, the full interface for Payment.find_all_by_amount is actually Payment.find_all_by_amount(amount, options). And the full interface to Person.find_by_user_name is actually Person.find_by_user_name(user_name, options). So you could call Payment.find_all_by_amount(50, :order => "created_on").

The same dynamic finder style can be used to create the object if it doesn‘t already exist. This dynamic finder is called with find_or_create_by_ and will return the object if it already exists and otherwise creates it, then returns it. Protected attributes won‘t be set unless they are given in a block. For example:

  # 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")

  # Now 'Bob' exist and is an 'admin'
  User.find_or_create_by_name('Bob', :age => 40) { |u| u.admin = true }

Use the find_or_initialize_by_ finder if you want to return a new record without saving it first. Protected attributes won‘t be setted unless they are given in a block. For example:

  # No 'Winter' tag exists
  winter = Tag.find_or_initialize_by_name("Winter")
  winter.new_record? # true

To find by a subset of the attributes to be used for instantiating a new object, pass a hash instead of a list of parameters. For example:

  Tag.find_or_create_by_name(:name => "rails", :creator => current_user)

That will either find an existing tag named "rails", or create a new one while setting the user that created it.

Saving arrays, hashes, and other non-mappable objects in text columns

Active Record can serialize any object in text columns using YAML. To do so, you must specify this with a call to the class method serialize. This makes it possible to store arrays, hashes, and other non-mappable objects without doing any additional work. Example:

  class User < ActiveRecord::Base
    serialize :preferences
  end

  user = User.create(:preferences => { "background" => "black", "display" => large })
  User.find(user.id).preferences # => { "background" => "black", "display" => large }

You can also specify a class option as the second parameter that‘ll raise an exception if a serialized object is retrieved as a descendent of a class not in the hierarchy. Example:

  class User < ActiveRecord::Base
    serialize :preferences, Hash
  end

  user = User.create(:preferences => %w( one two three ))
  User.find(user.id).preferences    # raises SerializationTypeMismatch

Single table inheritance

Active Record allows inheritance by storing the name of the class in a column that by default is named "type" (can be changed by overwriting Base.inheritance_column). This means that an inheritance looking like this:

  class Company < ActiveRecord::Base; end
  class Firm < Company; end
  class Client < Company; end
  class PriorityClient < Client; end

When you do Firm.create(:name => "37signals"), this record will be saved in the companies table with type = "Firm". You can then fetch this row again using Company.find(:first, "name = ‘37signals’") and it will return a Firm object.

If you don‘t have a type column defined in your table, single-table inheritance won‘t be triggered. In that case, it‘ll work just like normal subclasses with no special magic for differentiating between them or reloading the right type with find.

Note, all the attributes for all the cases are kept in the same table. Read more: www.martinfowler.com/eaaCatalog/singleTableInheritance.html

Connection to multiple databases in different models

Connections are usually created through ActiveRecord::Base.establish_connection and retrieved by ActiveRecord::Base.connection. All classes inheriting from ActiveRecord::Base will use this connection. But you can also set a class-specific connection. For example, if Course is an ActiveRecord::Base, but resides in a different database, you can just say Course.establish_connection and Course *and all its subclasses* will use this connection instead.

This feature is implemented by keeping a connection pool in ActiveRecord::Base that is a Hash indexed by the class. If a connection is requested, the retrieve_connection method will go up the class-hierarchy until a connection is found in the connection pool.

Exceptions

Note: The attributes listed are class-level attributes (accessible from both the class and instance level). So it‘s possible to assign a logger to the class through Base.logger= which will then be used by all instances in the current object space.

Child modules and classes

Class ActiveRecord::Base::ConnectionSpecification

Constants

NameValue
VALID_FIND_OPTIONS [ :conditions, :include, :joins, :limit, :offset, :order, :select, :readonly, :group, :from, :lock ]

Aliases

Old nameNew name
set_table_name table_name=
set_primary_key primary_key=
set_inheritance_column inheritance_column=
set_sequence_name sequence_name=
sanitize_sql_for_conditions sanitize_sql
sanitize_sql_hash_for_conditions sanitize_sql_hash
sanitize_sql sanitize_conditions

Attributes

NameRead/write?
abstract_class RW

Public Class Methods


=== (object)

Overwrite the default class equality method to provide support for association proxies.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1241
1241:       def ===(object)
1242:         object.is_a?(self)
1243:       end

abstract_class? ()

Returns whether this class is a base AR class. If A is a base class and B descends from A, then B.base_class will return B.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1257
1257:       def abstract_class?
1258:         defined?(@abstract_class) && @abstract_class == true
1259:       end

accessible_attributes (

Returns an array of all the attributes that have been made accessible to mass-assignment.

     # File vendor/rails/activerecord/lib/active_record/base.rb, line 890
890:       def accessible_attributes # nodoc
891:         read_inheritable_attribute("attr_accessible")
892:       end

active_connection_name (

    # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 54
54:       def active_connection_name #nodoc
55:         @active_connection_name ||=
56:            if active_connections[name] || @@defined_connections[name]
57:              name
58:            elsif self == ActiveRecord::Base
59:              nil
60:            else
61:              superclass.active_connection_name
62:            end
63:       end

allow_concurrency= (threaded)

set concurrency support flag (not thread safe, like most of the methods in this file)

    # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 41
41:       def allow_concurrency=(threaded) #nodoc
42:         logger.debug "allow_concurrency=#{threaded}" if logger
43:         return if @@allow_concurrency == threaded
44:         clear_all_cached_connections!
45:         @@allow_concurrency = threaded
46:         method_prefix = threaded ? "thread_safe" : "single_threaded"
47:         sing = (class << self; self; end)
48:         [:active_connections, :scoped_methods].each do |method|
49:           sing.send(:alias_method, method, "#{method_prefix}_#{method}")
50:         end
51:         log_connections if logger
52:       end

attr_accessible (*attributes)

Similar to the attr_protected macro, this protects attributes of your model from mass-assignment, such as new(attributes) and attributes=(attributes) 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

*attributes A comma separated list of symbols that represent columns not to be protected

Examples

  class Customer < ActiveRecord::Base
    attr_accessible :name, :nickname
  end

  customer = Customer.new(:name => "David", :nickname => "Dave", :credit_rating => "Excellent")
  customer.credit_rating # => nil
  customer.attributes = { :name => "Jolly fellow", :credit_rating => "Superb" }
  customer.credit_rating # => nil

  customer.credit_rating = "Average"
  customer.credit_rating # => "Average"
     # File vendor/rails/activerecord/lib/active_record/base.rb, line 885
885:       def attr_accessible(*attributes)
886:         write_inheritable_attribute("attr_accessible", Set.new(attributes.map(&:to_s)) + (accessible_attributes || []))
887:       end

attr_protected (*attributes)

Attributes named in this macro are protected from mass-assignment, such as new(attributes) and attributes=(attributes). Their assignment will simply be ignored. Instead, you can use the direct writer methods to do assignment. This is meant to protect sensitive attributes from being overwritten by URL/form hackers. Example:

  class Customer < ActiveRecord::Base
    attr_protected :credit_rating
  end

  customer = Customer.new("name" => David, "credit_rating" => "Excellent")
  customer.credit_rating # => nil
  customer.attributes = { "description" => "Jolly fellow", "credit_rating" => "Superb" }
  customer.credit_rating # => nil

  customer.credit_rating = "Average"
  customer.credit_rating # => "Average"

To start from an all-closed default and enable attributes as needed, have a look at attr_accessible.

     # File vendor/rails/activerecord/lib/active_record/base.rb, line 851
851:       def attr_protected(*attributes)
852:         write_inheritable_attribute("attr_protected", Set.new(attributes.map(&:to_s)) + (protected_attributes || []))
853:       end

attr_readonly (*attributes)

Attributes listed as readonly can be set for a new record, but will be ignored in database updates afterwards.

     # File vendor/rails/activerecord/lib/active_record/base.rb, line 895
895:        def attr_readonly(*attributes)
896:          write_inheritable_attribute("attr_readonly", Set.new(attributes.map(&:to_s)) + (readonly_attributes || []))
897:        end

base_class ()

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 through some arbitrarily deep hierarchy, B.base_class will return A.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1248
1248:       def base_class
1249:         class_of_active_record_descendant(self)
1250:       end

benchmark (title, log_level = Logger::DEBUG, use_silence = true) {|| ...}

Log and benchmark multiple statements in a single block. Example:

  Project.benchmark("Creating project") do
    project = Project.create("name" => "stuff")
    project.create_manager("name" => "David")
    project.milestones << Milestone.find(:all)
  end

The benchmark is only recorded if the current level of the logger is less than or equal to the log_level, which makes it easy to include benchmarking statements in production software that will remain inexpensive because the benchmark will only be conducted if the log level is low enough.

The logging of the multiple statements is turned off unless use_silence is set to false.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1221
1221:       def benchmark(title, log_level = Logger::DEBUG, use_silence = true)
1222:         if logger && logger.level <= log_level
1223:           result = nil
1224:           seconds = Benchmark.realtime { result = use_silence ? silence { yield } : yield }
1225:           logger.add(log_level, "#{title} (#{'%.5f' % seconds})")
1226:           result
1227:         else
1228:           yield
1229:         end
1230:       end

class_name (table_name = table_name)

Turns the table_name back into a class name following the reverse rules of table_name.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1091
1091:       def class_name(table_name = table_name) # nodoc
1092:         # remove any prefix and/or suffix from the table name
1093:         class_name = table_name[table_name_prefix.length..-(table_name_suffix.length + 1)].camelize
1094:         class_name = class_name.singularize if pluralize_table_names
1095:         class_name
1096:       end

clear_active_connection_name (

    # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 65
65:       def clear_active_connection_name #nodoc
66:         @active_connection_name = nil
67:         subclasses.each { |klass| klass.clear_active_connection_name }
68:       end

clear_active_connections! ()

Clears the cache which maps classes to connections.

    # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 84
84:       def clear_active_connections!
85:         clear_cache!(@@active_connections) do |name, conn|
86:           conn.disconnect!
87:         end
88:       end

clear_reloadable_connections! ()

Clears the cache which maps classes

     # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 91
 91:       def clear_reloadable_connections!
 92:         if @@allow_concurrency
 93:           # With concurrent connections @@active_connections is
 94:           # a hash keyed by thread id.
 95:           @@active_connections.each do |thread_id, conns|
 96:             conns.each do |name, conn|
 97:               if conn.requires_reloading?
 98:                 conn.disconnect!
 99:                 @@active_connections[thread_id].delete(name)
100:               end
101:             end
102:           end
103:         else
104:           @@active_connections.each do |name, conn|
105:             if conn.requires_reloading?
106:               conn.disconnect!
107:               @@active_connections.delete(name)
108:             end
109:           end
110:         end
111:       end

column_methods_hash (

Returns a hash of all the methods added to query each of the columns in the table with the name of the method as the key and true as the value. This makes it possible to do O(1) lookups in respond_to? to check if a given method for attribute is available.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1142
1142:       def column_methods_hash #nodoc
1143:         @dynamic_methods_hash ||= column_names.inject(Hash.new(false)) do |methods, attr|
1144:           attr_name = attr.to_s
1145:           methods[attr.to_sym]       = attr_name
1146:           methods["#{attr}=".to_sym] = attr_name
1147:           methods["#{attr}?".to_sym] = attr_name
1148:           methods["#{attr}_before_type_cast".to_sym] = attr_name
1149:           methods
1150:         end
1151:       end

column_names ()

Returns an array of column names as strings.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1129
1129:       def column_names
1130:         @column_names ||= columns.map { |column| column.name }
1131:       end

columns ()

Returns an array of column objects for the table associated with this class.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1115
1115:       def columns
1116:         unless defined?(@columns) && @columns
1117:           @columns = connection.columns(table_name, "#{name} Columns")
1118:           @columns.each { |column| column.primary = column.name == primary_key }
1119:         end
1120:         @columns
1121:       end

columns_hash ()

Returns a hash of column objects for the table associated with this class.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1124
1124:       def columns_hash
1125:         @columns_hash ||= columns.inject({}) { |hash, column| hash[column.name] = column; hash }
1126:       end

connected? ()

Returns true if a connection that‘s accessible to this class has already been opened.

     # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 268
268:     def self.connected?
269:       active_connections[active_connection_name] ? true : false
270:     end

connection ()

Returns the connection currently associated with the class. This can also be used to "borrow" the connection to do database work unrelated to any of the specific Active Records.

    # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 73
73:       def connection
74:         if defined?(@active_connection_name) && (conn = active_connections[@active_connection_name])
75:           conn
76:         else
77:           # retrieve_connection sets the cache key.
78:           conn = retrieve_connection
79:           active_connections[@active_connection_name] = conn
80:         end
81:       end

connection= (spec)

Set the connection for the class.

     # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 286
286:     def self.connection=(spec) #nodoc
287:       if spec.kind_of?(ActiveRecord::ConnectionAdapters::AbstractAdapter)
288:         active_connections[name] = spec
289:       elsif spec.kind_of?(ConnectionSpecification)
290:         config = spec.config.reverse_merge(:allow_concurrency => @@allow_concurrency)
291:         self.connection = self.send(spec.adapter_method, config)
292:       elsif spec.nil?
293:         raise ConnectionNotEstablished
294:       else
295:         establish_connection spec
296:       end
297:     end

content_columns ()

Returns an array of column objects where the primary id, all columns ending in "_id" or "_count", and columns used for single table inheritance have been removed.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1135
1135:       def content_columns
1136:         @content_columns ||= columns.reject { |c| c.primary || c.name =~ /(_id|_count)$/ || c.name == inheritance_column }
1137:       end

count_by_sql (sql)

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 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

  Product.count_by_sql "SELECT COUNT(*) FROM sales s, customers c WHERE s.customer_id = c.id"
     # File vendor/rails/activerecord/lib/active_record/base.rb, line 761
761:       def count_by_sql(sql)
762:         sql = sanitize_conditions(sql)
763:         connection.select_value(sql, "#{name} Count").to_i
764:       end

create (attributes = nil)

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 attributes on the objects that are to be created.

Examples

  # Create a single new object
  User.create(:first_name => 'Jamie')
  # Create an Array of new objects
  User.create([{:first_name => 'Jamie'}, {:first_name => 'Jeremy'}])
     # File vendor/rails/activerecord/lib/active_record/base.rb, line 595
595:       def create(attributes = nil)
596:         if attributes.is_a?(Array)
597:           attributes.collect { |attr| create(attr) }
598:         else
599:           object = new(attributes)
600:           object.save
601:           object
602:         end
603:       end

decrement_counter (counter_name, id)

Decrement a number field by one, usually representing a count.

This works the same as increment_counter but reduces the column value by 1 instead of increasing it.

Options

counter_name The name of the field that should be decremented id The id of the object that should be decremented

Examples

  # Decrement the post_count column for the record with an id of 5
  DiscussionBoard.decrement_counter(:post_count, 5)
     # File vendor/rails/activerecord/lib/active_record/base.rb, line 829
829:       def decrement_counter(counter_name, id)
830:         update_counters(id, counter_name => -1)
831:       end

delete (id)

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)
     # File vendor/rails/activerecord/lib/active_record/base.rb, line 650
650:       def delete(id)
651:         delete_all([ "#{connection.quote_column_name(primary_key)} IN (?)", id ])
652:       end

delete_all (conditions = nil)

Deletes the records matching conditions without instantiating the records first, and hence not calling the destroy method and invoking callbacks. This is a single SQL query, much more efficient than destroy_all.

Options

conditions Conditions are specified the same way as with find method.

Example

  Post.delete_all "person_id = 5 AND (category = 'Something' OR category = 'Else')"

This deletes the affected posts all at once with a single DELETE query. If you need to destroy dependent associations or call your before_ or after_destroy callbacks, use the destroy_all method instead.

     # File vendor/rails/activerecord/lib/active_record/base.rb, line 744
744:       def delete_all(conditions = nil)
745:         sql = "DELETE FROM #{quoted_table_name} "
746:         add_conditions!(sql, conditions, scope(:find))
747:         connection.delete(sql, "#{name} Delete all")
748:       end

descends_from_active_record? ()

True if this isn‘t a concrete subclass needing a STI type condition.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1171
1171:       def descends_from_active_record?
1172:         if superclass.abstract_class?
1173:           superclass.descends_from_active_record?
1174:         else
1175:           superclass == Base || !columns_hash.include?(inheritance_column)
1176:         end
1177:       end

destroy (id)

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 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)
     # File vendor/rails/activerecord/lib/active_record/base.rb, line 673
673:       def destroy(id)
674:         if id.is_a?(Array)
675:           id.map { |one_id| destroy(one_id) }
676:         else
677:           find(id).destroy
678:         end
679:       end

destroy_all (conditions = nil)

Destroys the records matching conditions by instantiating each record and calling the destroy method. This means at least 2*N database queries to destroy N records, so avoid destroy_all if you are deleting many records. If you want to simply delete records without worrying about dependent associations or callbacks, use the much faster delete_all method instead.

Options

conditions Conditions are specified the same way as with find method.

Example

  Person.destroy_all "last_login < '2004-04-04'"

This loads and destroys each person one by one, including its dependent associations and before_ and after_destroy callbacks.

     # File vendor/rails/activerecord/lib/active_record/base.rb, line 726
726:       def destroy_all(conditions = nil)
727:         find(:all, :conditions => conditions).each { |object| object.destroy }
728:       end

establish_connection (spec = nil)

Establishes the connection to the database. Accepts a hash as input where the :adapter key must be specified with the name of a database adapter (in lower-case) example for regular databases (MySQL, Postgresql, etc):

  ActiveRecord::Base.establish_connection(
    :adapter  => "mysql",
    :host     => "localhost",
    :username => "myuser",
    :password => "mypass",
    :database => "somedatabase"
  )

Example for SQLite database:

  ActiveRecord::Base.establish_connection(
    :adapter => "sqlite",
    :database  => "path/to/dbfile"
  )

Also accepts keys as strings (for parsing from yaml for example):

  ActiveRecord::Base.establish_connection(
    "adapter" => "sqlite",
    "database"  => "path/to/dbfile"
  )

The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError may be returned on an error.

     # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 204
204:     def self.establish_connection(spec = nil)
205:       case spec
206:         when nil
207:           raise AdapterNotSpecified unless defined? RAILS_ENV
208:           establish_connection(RAILS_ENV)
209:         when ConnectionSpecification
210:           clear_active_connection_name
211:           @active_connection_name = name
212:           @@defined_connections[name] = spec
213:         when Symbol, String
214:           if configuration = configurations[spec.to_s]
215:             establish_connection(configuration)
216:           else
217:             raise AdapterNotSpecified, "#{spec} database is not configured"
218:           end
219:         else
220:           spec = spec.symbolize_keys
221:           unless spec.key?(:adapter) then raise AdapterNotSpecified, "database configuration does not specify adapter" end
222: 
223:           begin
224:             require 'rubygems'
225:             gem "activerecord-#{spec[:adapter]}-adapter"
226:             require "active_record/connection_adapters/#{spec[:adapter]}_adapter"
227:           rescue LoadError
228:             begin
229:               require "active_record/connection_adapters/#{spec[:adapter]}_adapter"
230:             rescue LoadError
231:               raise "Please install the #{spec[:adapter]} adapter: `gem install activerecord-#{spec[:adapter]}-adapter` (#{$!})"
232:             end
233:           end
234: 
235:           adapter_method = "#{spec[:adapter]}_connection"
236:           if !respond_to?(adapter_method)
237:             raise AdapterNotFound, "database configuration specifies nonexistent #{spec[:adapter]} adapter"
238:           end
239: 
240:           remove_connection
241:           establish_connection(ConnectionSpecification.new(spec, adapter_method))
242:       end
243:     end

exists? (id_or_conditions)

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 an Array or a Hash.

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

  Person.exists?(5)
  Person.exists?('5')
  Person.exists?(:name => "David")
  Person.exists?(['name LIKE ?', "%#{query}%"])
     # File vendor/rails/activerecord/lib/active_record/base.rb, line 573
573:       def exists?(id_or_conditions)
574:         connection.select_all(
575:           construct_finder_sql(
576:             :select     => "#{quoted_table_name}.#{primary_key}", 
577:             :conditions => expand_id_conditions(id_or_conditions), 
578:             :limit      => 1
579:           ), 
580:           "#{name} Exists"
581:         ).size > 0
582:       end

find (*args)

Find operates with four different retrieval approaches:

  • Find by id: This can either be a specific id (1), a list of ids (1, 5, 6), or an array of ids ([5, 6, 10]). If no record can be found for all of the listed ids, then RecordNotFound will be raised.
  • Find first: This will return the first record matched by the options used. These options can either be specific conditions or merely an order. If no record can be matched, nil is returned.
  • Find last: This will return the last record matched by the options used. These options can either be specific conditions or merely an order. If no record can be matched, nil is returned.
  • Find all: This will return all the records matched by the options used. If no records are found, an empty array is returned.

All approaches accept an options hash as their last parameter. The options are:

  • :conditions: An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro.
  • :order: An SQL fragment like "created_at DESC, name".
  • :group: An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause.
  • :limit: An integer determining the limit on the number of rows that should be returned.
  • :offset: An integer determining the offset from where the rows should be fetched. So at 5, it would skip rows 0 through 4.
  • :joins: Either an SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id" (rarely needed) or named associations in the same form used for the :include option, which will perform an INNER JOIN on the associated table(s). If the value is a string, then the records will be returned read-only since they will have attributes that do not correspond to the table‘s columns. Pass :readonly => false to override.
  • :include: Names associations that should be loaded alongside using LEFT OUTER JOINs. The symbols named refer to already defined associations. See eager loading under Associations.
  • :select: 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.
  • :from: 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).
  • :readonly: Mark the returned records read-only so they cannot be saved or updated.
  • :lock: An SQL fragment like "FOR UPDATE" or "LOCK IN SHARE MODE". :lock => true gives connection‘s default exclusive lock, usually "FOR UPDATE".

Examples for find by id:

  Person.find(1)       # returns the object for ID = 1
  Person.find(1, 2, 6) # returns an array for objects with IDs in (1, 2, 6)
  Person.find([7, 17]) # returns an array for objects with IDs in (7, 17)
  Person.find([1])     # returns an array for the object with ID = 1
  Person.find(1, :conditions => "administrator = 1", :order => "created_on DESC")

Note that returned records may not be in the same order as the ids you provide since database rows are unordered. Give an explicit :order to ensure the results are sorted.

Examples for find first:

  Person.find(:first) # returns the first object fetched by SELECT * FROM people
  Person.find(:first, :conditions => [ "user_name = ?", user_name])
  Person.find(:first, :order => "created_on DESC", :offset => 5)

Examples for find last:

  Person.find(:last) # returns the last object fetched by SELECT * FROM people
  Person.find(:last, :conditions => [ "user_name = ?", user_name])
  Person.find(:last, :order => "created_on DESC", :offset => 5)

Examples for find all:

  Person.find(:all) # returns an array of objects for all the rows fetched by SELECT * FROM people
  Person.find(:all, :conditions => [ "category IN (?)", categories], :limit => 50)
  Person.find(:all, :offset => 10, :limit => 10)
  Person.find(:all, :include => [ :account, :friends ])
  Person.find(:all, :group => "category")

Example for find with a lock. Imagine two concurrent transactions: each will read person.visits == 2, add 1 to it, and save, resulting in two saves of person.visits = 3. By locking the row, the second transaction has to wait until the first is finished; we get the expected person.visits == 4.

  Person.transaction do
    person = Person.find(1, :lock => true)
    person.visits += 1
    person.save!
  end
     # File vendor/rails/activerecord/lib/active_record/base.rb, line 505
505:       def find(*args)
506:         options = args.extract_options!
507:         validate_find_options(options)
508:         set_readonly_option!(options)
509: 
510:         case args.first
511:           when :first then find_initial(options)
512:           when :last  then find_last(options)
513:           when :all   then find_every(options)
514:           else             find_from_ids(args, options)
515:         end
516:       end

find_by_sql (sql)

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 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 change your call if you switch engines

Examples

  # A simple sql query spanning multiple tables
  Post.find_by_sql "SELECT p.title, c.author FROM posts p, comments c WHERE p.id = c.post_id"
  > [#<Post:0x36bff9c @attributes={"title"=>"Ruby Meetup", "first_name"=>"Quentin"}>, ...]

  # You can use the same string replacement techniques as you can with ActiveRecord#find
  Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]
  > [#<Post:0x36bff9c @attributes={"first_name"=>"The Cheap Man Buys Twice"}>, ...]
     # File vendor/rails/activerecord/lib/active_record/base.rb, line 553
553:       def find_by_sql(sql)
554:         connection.select_all(sanitize_sql(sql), "#{name} Load").collect! { |record| instantiate(record) }
555:       end

finder_needs_type_condition? (

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1179
1179:       def finder_needs_type_condition? #nodoc
1180:         # This is like this because benchmarking justifies the strange :false stuff
1181:         :true == (@finder_needs_type_condition ||= descends_from_active_record? ? :false : :true)
1182:       end

first (*args)

This is an alias for find(:first). You can pass in all the same arguments to this method as you can to find(:first)

     # File vendor/rails/activerecord/lib/active_record/base.rb, line 520
520:       def first(*args)
521:         find(:first, *args)
522:       end

get_primary_key (base_name)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 997
 997:       def get_primary_key(base_name) #nodoc
 998:         key = 'id'
 999:         case primary_key_prefix_type
1000:           when :table_name
1001:             key = Inflector.foreign_key(base_name, false)
1002:           when :table_name_with_underscore
1003:             key = Inflector.foreign_key(base_name)
1004:         end
1005:         key
1006:       end

human_attribute_name (attribute_key_name)

Transforms attribute key names into a more humane format, such as "First name" instead of "first_name". Example:

  Person.human_attribute_name("first_name") # => "First name"

Deprecated in favor of just calling "first_name".humanize

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1166
1166:       def human_attribute_name(attribute_key_name) #nodoc
1167:         attribute_key_name.humanize
1168:       end

increment_counter (counter_name, id)

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 shown it would have to run an SQL query to find how many posts and comments there are.

Options

counter_name The name of the field that should be incremented id The id of the object that should be incremented

Examples

  # Increment the post_count column for the record with an id of 5
  DiscussionBoard.increment_counter(:post_count, 5)
     # File vendor/rails/activerecord/lib/active_record/base.rb, line 812
812:       def increment_counter(counter_name, id)
813:         update_counters(id, counter_name => 1)
814:       end

inheritance_column ()

Defines the column name for use with single table inheritance — can be set in subclasses like so: self.inheritance_column = "type_id"

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1010
1010:       def inheritance_column
1011:         @inheritance_column ||= "type".freeze
1012:       end

inherited (child)

     # File vendor/rails/activerecord/lib/active_record/base.rb, line 361
361:     def self.inherited(child) #nodoc
362:       @@subclasses[self] ||= []
363:       @@subclasses[self] << child
364:       super
365:     end

inspect ()

Returns a string like ‘Post id:integer, title:string, body:text‘

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1185
1185:       def inspect
1186:         if self == Base
1187:           super
1188:         elsif abstract_class?
1189:           "#{super}(abstract)"
1190:         elsif table_exists?
1191:           attr_list = columns.map { |c| "#{c.name}: #{c.type}" } * ', '
1192:           "#{super}(#{attr_list})"
1193:         else
1194:           "#{super}(Table doesn't exist)"
1195:         end
1196:       end

last (*args)

This is an alias for find(:last). You can pass in all the same arguments to this method as you can to find(:last)

     # File vendor/rails/activerecord/lib/active_record/base.rb, line 526
526:       def last(*args)
527:         find(:last, *args)
528:       end

log_connections (

connection state logging

     # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 300
300:     def self.log_connections #nodoc
301:       if logger
302:         logger.info "Defined connections: #{@@defined_connections.inspect}"
303:         logger.info "Active connections: #{active_connections.inspect}"
304:         logger.info "Active connection name: #{@active_connection_name}"
305:       end
306:     end

mysql_connection (config)

Establishes a connection to the database that‘s used by all Active Record objects.

    # File vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb, line 72
72:     def self.mysql_connection(config) # nodoc
73:       config = config.symbolize_keys
74:       host     = config[:host]
75:       port     = config[:port]
76:       socket   = config[:socket]
77:       username = config[:username] ? config[:username].to_s : 'root'
78:       password = config[:password].to_s
79: 
80:       if config.has_key?(:database)
81:         database = config[:database]
82:       else
83:         raise ArgumentError, "No database specified. Missing argument: database."
84:       end
85: 
86:       require_mysql
87:       mysql = Mysql.init
88:       mysql.ssl_set(config[:sslkey], config[:sslcert], config[:sslca], config[:sslcapath], config[:sslcipher]) if config[:sslkey]
89: 
90:       ConnectionAdapters::MysqlAdapter.new(mysql, logger, [host, username, password, database, port, socket], config)
91:     end

new (attributes = nil) {|self if block_given?| ...}

New objects can be instantiated as either empty (pass no construction parameter) or pre-set with attributes but not yet saved (pass a hash with key names matching the associated table column names). In both instances, valid attribute keys are determined by the column names of the associated table — hence you can‘t have attributes that aren‘t part of the table columns.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2072
2072:       def initialize(attributes = nil)
2073:         @attributes = attributes_from_column_definition
2074:         @attributes_cache = {}
2075:         @new_record = true
2076:         ensure_proper_type
2077:         self.attributes = attributes unless attributes.nil?
2078:         self.class.send(:scope, :create).each { |att,value| self.send("#{att}=", value) } if self.class.send(:scoped?, :create)
2079:         result = yield self if block_given?
2080:         callback(:after_initialize) if respond_to_without_attributes?(:after_initialize)
2081:         result
2082:       end

postgresql_connection (config)

Establishes a connection to the database that‘s used by all Active Record objects

    # File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 22
22:     def self.postgresql_connection(config) # nodoc
23:       config = config.symbolize_keys
24:       host     = config[:host]
25:       port     = config[:port] || 5432
26:       username = config[:username].to_s
27:       password = config[:password].to_s
28: 
29:       if config.has_key?(:database)
30:         database = config[:database]
31:       else
32:         raise ArgumentError, "No database specified. Missing argument: database."
33:       end
34: 
35:       # The postgres drivers don't allow the creation of an unconnected PGconn object,
36:       # so just pass a nil connection object for the time being.
37:       ConnectionAdapters::PostgreSQLAdapter.new(nil, logger, [host, port, nil, nil, database, username, password], config)
38:     end

primary_key ()

Defines the primary key field — can be overridden in subclasses. Overwriting will negate any effect of the primary_key_prefix_type setting, though.

     # File vendor/rails/activerecord/lib/active_record/base.rb, line 987
987:       def primary_key
988:         reset_primary_key
989:       end

protected_attributes (

Returns an array of all the attributes that have been protected from mass-assignment.

     # File vendor/rails/activerecord/lib/active_record/base.rb, line 856
856:       def protected_attributes # nodoc
857:         read_inheritable_attribute("attr_protected")
858:       end

quote_value (value, column = nil)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1199
1199:       def quote_value(value, column = nil) #nodoc
1200:         connection.quote(value,column)
1201:       end

readonly_attributes ()

Returns an array of all the attributes that have been specified as readonly.

     # File vendor/rails/activerecord/lib/active_record/base.rb, line 900
900:        def readonly_attributes
901:          read_inheritable_attribute("attr_readonly")
902:        end

remove_connection (klass=self)

Remove the connection for this class. This will close the active connection and the defined connection (if they exist). The result can be used as an argument for establish_connection, for easily re-establishing the connection.

     # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 276
276:     def self.remove_connection(klass=self)
277:       spec = @@defined_connections[klass.name]
278:       konn = active_connections[klass.name]
279:       @@defined_connections.delete_if { |key, value| value == spec }
280:       active_connections.delete_if { |key, value| value == konn }
281:       konn.disconnect! if konn
282:       spec.config if spec
283:     end

require_mysql ()

    # File vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb, line 47
47:     def self.require_mysql
48:       # Include the MySQL driver if one hasn't already been loaded
49:       unless defined? Mysql
50:         begin
51:           require_library_or_gem 'mysql'
52:         rescue LoadError => cannot_require_mysql
53:           # Use the bundled Ruby/MySQL driver if no driver is already in place
54:           begin
55:             ActiveRecord::Base.logger.info(
56:               "WARNING: You're using the Ruby-based MySQL library that ships with Rails. This library is not suited for production. " +
57:               "Please install the C-based MySQL library instead (gem install mysql)."
58:             ) if ActiveRecord::Base.logger
59: 
60:             require 'active_record/vendor/mysql'
61:           rescue LoadError
62:             raise cannot_require_mysql
63:           end
64:         end
65:       end
66: 
67:       # Define Mysql::Result.all_hashes
68:       MysqlCompat.define_all_hashes_method!
69:     end

reset_column_information ()

Resets all the cached information about columns, which will cause them to be reloaded on the next request.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1154
1154:       def reset_column_information
1155:         generated_methods.each { |name| undef_method(name) }
1156:         @column_names = @columns = @columns_hash = @content_columns = @dynamic_methods_hash = @generated_methods = @inheritance_column = nil
1157:       end

reset_column_information_and_inheritable_attributes_for_all_subclasses (

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1159
1159:       def reset_column_information_and_inheritable_attributes_for_all_subclasses#nodoc
1160:         subclasses.each { |klass| klass.reset_inheritable_attributes; klass.reset_column_information }
1161:       end

reset_primary_key (

     # File vendor/rails/activerecord/lib/active_record/base.rb, line 991
991:       def reset_primary_key #nodoc
992:         key = get_primary_key(base_class.name)
993:         set_primary_key(key)
994:         key
995:       end

reset_sequence_name (

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1020
1020:       def reset_sequence_name #nodoc
1021:         default = connection.default_sequence_name(table_name, primary_key)
1022:         set_sequence_name(default)
1023:         default
1024:       end

reset_subclasses (

     # File vendor/rails/activerecord/lib/active_record/base.rb, line 367
367:     def self.reset_subclasses #nodoc
368:       nonreloadables = []
369:       subclasses.each do |klass|
370:         unless Dependencies.autoloaded? klass
371:           nonreloadables << klass
372:           next
373:         end
374:         klass.instance_variables.each { |var| klass.send(:remove_instance_variable, var) }
375:         klass.instance_methods(false).each { |m| klass.send :undef_method, m }
376:       end
377:       @@subclasses = {}
378:       nonreloadables.each { |klass| (@@subclasses[klass.superclass] ||= []) << klass }
379:     end

reset_table_name (

     # File vendor/rails/activerecord/lib/active_record/base.rb, line 964
964:       def reset_table_name #nodoc
965:         base = base_class
966: 
967:         name =
968:           # STI subclasses always use their superclass' table.
969:           unless self == base
970:             base.table_name
971:           else
972:             # Nested classes are prefixed with singular parent table name.
973:             if parent < ActiveRecord::Base && !parent.abstract_class?
974:               contained = parent.table_name
975:               contained = contained.singularize if parent.pluralize_table_names
976:               contained << '_'
977:             end
978:             name = "#{table_name_prefix}#{contained}#{undecorated_table_name(base.name)}#{table_name_suffix}"
979:           end
980: 
981:         set_table_name(name)
982:         name
983:       end

retrieve_connection (

Locate the connection of the nearest super class. This can be an active or defined connection: if it is the latter, it will be opened and set as the active connection for the class it was defined for (not necessarily the current class).

     # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 249
249:     def self.retrieve_connection #nodoc
250:       # Name is nil if establish_connection hasn't been called for
251:       # some class along the inheritance chain up to AR::Base yet.
252:       if name = active_connection_name
253:         if conn = active_connections[name]
254:           # Verify the connection.
255:           conn.verify!(@@verification_timeout)
256:         elsif spec = @@defined_connections[name]
257:           # Activate this connection specification.
258:           klass = name.constantize
259:           klass.connection = spec
260:           conn = active_connections[name]
261:         end
262:       end
263: 
264:       conn or raise ConnectionNotEstablished
265:     end

sanitize (object)

Used to sanitize objects before they‘re used in an SQL SELECT statement. Delegates to connection.quote.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1204
1204:       def sanitize(object) #nodoc
1205:         connection.quote(object)
1206:       end

sequence_name (

Lazy-set the sequence name to the connection‘s default. This method is only ever called once since set_sequence_name overrides it.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1016
1016:       def sequence_name #nodoc
1017:         reset_sequence_name
1018:       end

serialize (attr_name, class_name = Object)

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

attr_name The field name that should be serialized class_name Optional, class name that the object type should be equal to

Example

  # Serialize a preferences attribute
  class User
    serialize :preferences
  end
     # File vendor/rails/activerecord/lib/active_record/base.rb, line 919
919:       def serialize(attr_name, class_name = Object)
920:         serialized_attributes[attr_name.to_s] = class_name
921:       end

serialized_attributes ()

Returns a hash of all the attributes that have been specified for serialization as keys and their class restriction as values.

     # File vendor/rails/activerecord/lib/active_record/base.rb, line 924
924:       def serialized_attributes
925:         read_inheritable_attribute("attr_serialized") or write_inheritable_attribute("attr_serialized", {})
926:       end

set_inheritance_column (value = nil, &block)

Sets the name of the inheritance column to use to the given value, or (if the value # is nil or false) to the value returned by the given block.

Example:

  class Project < ActiveRecord::Base
    set_inheritance_column do
      original_inheritance_column + "_id"
    end
  end
      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1064
1064:       def set_inheritance_column(value = nil, &block)
1065:         define_attr_method :inheritance_column, value, &block
1066:       end

set_primary_key (value = nil, &block)

Sets the name of the primary key column to use to the given value, or (if the value is nil or false) to the value returned by the given block.

Example:

  class Project < ActiveRecord::Base
    set_primary_key "sysid"
  end
      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1048
1048:       def set_primary_key(value = nil, &block)
1049:         define_attr_method :primary_key, value, &block
1050:       end

set_sequence_name (value = nil, &block)

Sets the name of the sequence to use when generating ids to the given value, or (if the value is nil or false) to the value returned by the given block. This is required for Oracle and is useful for any database which relies on sequences for primary key generation.

If a sequence name is not explicitly set when using Oracle or Firebird, it will default to the commonly used pattern of: #{table_name}_seq

If a sequence name is not explicitly set when using PostgreSQL, it will discover the sequence corresponding to your primary key for you.

Example:

  class Project < ActiveRecord::Base
    set_sequence_name "projectseq"   # default would have been "project_seq"
  end
      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1085
1085:       def set_sequence_name(value = nil, &block)
1086:         define_attr_method :sequence_name, value, &block
1087:       end

set_table_name (value = nil, &block)

Sets the table name to use to the given value, or (if the value is nil or false) to the value returned by the given block.

Example:

  class Project < ActiveRecord::Base
    set_table_name "project"
  end
      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1034
1034:       def set_table_name(value = nil, &block)
1035:         define_attr_method :table_name, value, &block
1036:       end

silence () {|| ...}

Silences the logger for the duration of the block.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1233
1233:       def silence
1234:         old_logger_level, logger.level = logger.level, Logger::ERROR if logger
1235:         yield
1236:       ensure
1237:         logger.level = old_logger_level if logger
1238:       end

single_threaded_active_connections (

    # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 29
29:       def single_threaded_active_connections #nodoc
30:         @@active_connections
31:       end

sqlite3_connection (config)

sqlite3 adapter reuses sqlite_connection.

    # File vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 6
 6:     def self.sqlite3_connection(config) # nodoc
 7:       parse_sqlite_config!(config)
 8: 
 9:       unless self.class.const_defined?(:SQLite3)
10:         require_library_or_gem(config[:adapter])
11:       end
12: 
13:       db = SQLite3::Database.new(
14:         config[:database],
15:         :results_as_hash => true,
16:         :type_translation => false
17:       )
18: 
19:       db.busy_timeout(config[:timeout]) unless config[:timeout].nil?
20: 
21:       ConnectionAdapters::SQLite3Adapter.new(db, logger)
22:     end

sqlite_connection (config)

Establishes a connection to the database that‘s used by all Active Record objects

    # File vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb, line 7
 7:       def sqlite_connection(config) # nodoc
 8:         parse_sqlite_config!(config)
 9: 
10:         unless self.class.const_defined?(:SQLite)
11:           require_library_or_gem(config[:adapter])
12: 
13:           db = SQLite::Database.new(config[:database], 0)
14:           db.show_datatypes   = "ON" if !defined? SQLite::Version
15:           db.results_as_hash  = true if defined? SQLite::Version
16:           db.type_translation = false
17: 
18:           # "Downgrade" deprecated sqlite API
19:           if SQLite.const_defined?(:Version)
20:             ConnectionAdapters::SQLite2Adapter.new(db, logger)
21:           else
22:             ConnectionAdapters::DeprecatedSQLiteAdapter.new(db, logger)
23:           end
24:         end
25:       end

table_exists? ()

Indicates whether the table associated with this class exists

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1099
1099:       def table_exists?
1100:         if connection.respond_to?(:tables)
1101:           connection.tables.include? table_name
1102:         else
1103:           # if the connection adapter hasn't implemented tables, there are two crude tests that can be
1104:           # used - see if getting column info raises an error, or if the number of columns returned is zero
1105:           begin
1106:             reset_column_information
1107:             columns.size > 0
1108:           rescue ActiveRecord::StatementInvalid
1109:             false
1110:           end
1111:         end
1112:       end

table_name ()

Guesses the table name (in forced lower-case) based on the name of the class in the inheritance hierarchy descending directly from ActiveRecord. So if the hierarchy looks like: Reply < Message < ActiveRecord, then Message is used to guess the table name even when called on Reply. The rules used to do the guess are handled by the Inflector class in Active Support, which knows almost all common English inflections. You can add new inflections in config/initializers/inflections.rb.

Nested classes are given table names prefixed by the singular form of the parent‘s table name. Enclosing modules are not considered. Examples:

  class Invoice < ActiveRecord::Base; end;
  file                  class               table_name
  invoice.rb            Invoice             invoices

  class Invoice < ActiveRecord::Base; class Lineitem < ActiveRecord::Base; end; end;
  file                  class               table_name
  invoice.rb            Invoice::Lineitem   invoice_lineitems

  module Invoice; class Lineitem < ActiveRecord::Base; end; end;
  file                  class               table_name
  invoice/lineitem.rb   Invoice::Lineitem   lineitems

Additionally, the class-level table_name_prefix is prepended and the table_name_suffix is appended. So if you have "myapp_" as a prefix, the table name guess for an Invoice class becomes "myapp_invoices". Invoice::Lineitem becomes "myapp_invoice_lineitems".

You can also overwrite this class method to allow for unguessable links, such as a Mouse class with a link to a "mice" table. Example:

  class Mouse < ActiveRecord::Base
    set_table_name "mice"
  end
     # File vendor/rails/activerecord/lib/active_record/base.rb, line 960
960:       def table_name
961:         reset_table_name
962:       end

thread_safe_active_connections (

Retrieve the connection cache.

    # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 25
25:       def thread_safe_active_connections #nodoc
26:         @@active_connections[Thread.current.object_id] ||= {}
27:       end

update (id, attributes)

Updates 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.

Options

id This should be the id or an array of ids to be updated attributes This should be a Hash of attributes to be set on the object, or an array of Hashes.

Examples

  # Updating one record:
  Person.update(15, {:user_name => 'Samuel', :group => 'expert'})

  # Updating multiple records:
  people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy"} }
  Person.update(people.keys, people.values)
     # File vendor/rails/activerecord/lib/active_record/base.rb, line 621
621:       def update(id, attributes)
622:         if id.is_a?(Array)
623:           idx = -1
624:           id.collect { |one_id| idx += 1; update(one_id, attributes[idx]) }
625:         else
626:           object = find(id)
627:           object.update_attributes(attributes)
628:           object
629:         end
630:       end

update_all (updates, conditions = nil, options = {})

Updates all records with details given if they match a set of conditions supplied, limits and order can also be supplied.

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 ].

              See conditions in the intro for more info.

options Additional options are :limit and/or :order, see the examples for usage.

Examples

  # 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%'",
                        :order => 'created_at', :limit => 5 )
     # File vendor/rails/activerecord/lib/active_record/base.rb, line 702
702:       def update_all(updates, conditions = nil, options = {})
703:         sql  = "UPDATE #{quoted_table_name} SET #{sanitize_sql_for_assignment(updates)} "
704:         scope = scope(:find)
705:         add_conditions!(sql, conditions, scope)
706:         add_order!(sql, options[:order], nil)
707:         add_limit!(sql, options, nil)
708:         connection.update(sql, "#{name} Update")
709:       end

update_counters (id, counters)

A generic "counter updater" implementation, intended primarily to be used by increment_counter and decrement_counter, but which may also be useful on its own. It simply does a direct SQL update for the record with the given ID, altering the given hash of counters by the amount 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

            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
  # increment the action_count by 1
  Post.update_counters 5, :comment_count => -1, :action_count => 1
  # Executes the following SQL:
  # UPDATE posts
  #    SET comment_count = comment_count - 1,
  #        action_count = action_count + 1
  #  WHERE id = 5
     # File vendor/rails/activerecord/lib/active_record/base.rb, line 789
789:       def update_counters(id, counters)
790:         updates = counters.inject([]) { |list, (counter_name, increment)|
791:           sign = increment < 0 ? "-" : "+"
792:           list << "#{connection.quote_column_name(counter_name)} = #{connection.quote_column_name(counter_name)} #{sign} #{increment.abs}"
793:         }.join(", ")
794:         update_all(updates, "#{connection.quote_column_name(primary_key)} = #{quote_value(id)}")
795:       end

verify_active_connections! (

Verify active connections.

     # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 114
114:       def verify_active_connections! #nodoc
115:         if @@allow_concurrency
116:           remove_stale_cached_threads!(@@active_connections) do |name, conn|
117:             conn.disconnect!
118:           end
119:         end
120:         
121:         active_connections.each_value do |connection|
122:           connection.verify!(@@verification_timeout)
123:         end
124:       end

Protected Class Methods


aggregate_mapping (reflection)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1903
1903:         def aggregate_mapping(reflection)
1904:           mapping = reflection.options[:mapping] || [reflection.name, reflection.name]
1905:           mapping.first.is_a?(Array) ? mapping : [mapping]
1906:         end

class_name_of_active_record_descendant (klass)

Returns the name of the class descending directly from ActiveRecord in the inheritance hierarchy.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1874
1874:         def class_name_of_active_record_descendant(klass) #nodoc
1875:           klass.base_class.name
1876:         end

class_of_active_record_descendant (klass)

Returns the class descending directly from ActiveRecord in the inheritance hierarchy.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1863
1863:         def class_of_active_record_descendant(klass)
1864:           if klass.superclass == Base || klass.superclass.abstract_class?
1865:             klass
1866:           elsif klass.superclass.nil?
1867:             raise ActiveRecordError, "#{name} doesn't belong in a hierarchy descending from ActiveRecord"
1868:           else
1869:             class_of_active_record_descendant(klass.superclass)
1870:           end
1871:         end

compute_type (type_name)

Returns the class type of the record using the current module as a prefix. So descendents of MyApp::Business::Account would appear as MyApp::Business::AccountSubclass.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1853
1853:         def compute_type(type_name)
1854:           modularized_name = type_name_with_module(type_name)
1855:           begin
1856:             class_eval(modularized_name, __FILE__, __LINE__)
1857:           rescue NameError
1858:             class_eval(type_name, __FILE__, __LINE__)
1859:           end
1860:         end

current_scoped_methods (

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1847
1847:         def current_scoped_methods #nodoc
1848:           scoped_methods.last
1849:         end

encode_quoted_value (value)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2060
2060:         def encode_quoted_value(value) #nodoc
2061:           quoted_value = connection.quote(value)
2062:           quoted_value = "'#{quoted_value[1..-2].gsub(/\'/, "\\\\'")}'" if quoted_value.include?("\\\'") # (for ruby mode) "
2063:           quoted_value
2064:         end

expand_hash_conditions_for_aggregates (attrs)

Accepts a hash of sql conditions and replaces those attributes that correspond to a composed_of relationship with their expanded aggregate attribute values. Given:

    class Person < ActiveRecord::Base
      composed_of :address, :class_name => "Address",
        :mapping => [%w(address_street street), %w(address_city city)]
    end

Then:

    { :address => Address.new("813 abc st.", "chicago") }
      # => { :address_street => "813 abc st.", :address_city => "chicago" }
      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1919
1919:         def expand_hash_conditions_for_aggregates(attrs)
1920:           expanded_attrs = {}
1921:           attrs.each do |attr, value|
1922:             unless (aggregation = reflect_on_aggregation(attr.to_sym)).nil?
1923:               mapping = aggregate_mapping(aggregation)
1924:               mapping.each do |field_attr, aggregate_attr|
1925:                 if mapping.size == 1 && !value.respond_to?(aggregate_attr)
1926:                   expanded_attrs[field_attr] = value
1927:                 else
1928:                   expanded_attrs[field_attr] = value.send(aggregate_attr)
1929:                 end
1930:               end
1931:             else
1932:               expanded_attrs[attr] = value
1933:             end
1934:           end
1935:           expanded_attrs
1936:         end

expand_range_bind_variables (bind_vars)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2013
2013:         def expand_range_bind_variables(bind_vars) #nodoc
2014:           bind_vars.sum do |var|
2015:             if var.is_a?(Range)
2016:               [var.first, var.last]
2017:             else
2018:               [var]
2019:             end
2020:           end
2021:         end

quote_bound_value (value)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2023
2023:         def quote_bound_value(value) #nodoc
2024:           if value.respond_to?(:map) && !value.is_a?(String)
2025:             if value.respond_to?(:empty?) && value.empty?
2026:               connection.quote(nil)
2027:             else
2028:               value.map { |v| connection.quote(v) }.join(',')
2029:             end
2030:           else
2031:             connection.quote(value)
2032:           end
2033:         end

raise_if_bind_arity_mismatch (statement, expected, provided)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2035
2035:         def raise_if_bind_arity_mismatch(statement, expected, provided) #nodoc
2036:           unless expected == provided
2037:             raise PreparedStatementInvalid, "wrong number of bind variables (#{provided} for #{expected}) in: #{statement}"
2038:           end
2039:         end

replace_bind_variables (statement, values)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1996
1996:         def replace_bind_variables(statement, values) #nodoc
1997:           raise_if_bind_arity_mismatch(statement, statement.count('?'), values.size)
1998:           bound = values.dup
1999:           statement.gsub('?') { quote_bound_value(bound.shift) }
2000:         end

replace_named_bind_variables (statement, bind_vars)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2002
2002:         def replace_named_bind_variables(statement, bind_vars) #nodoc
2003:           statement.gsub(/:([a-zA-Z]\w*)/) do
2004:             match = $1.to_sym
2005:             if bind_vars.include?(match)
2006:               quote_bound_value(bind_vars[match])
2007:             else
2008:               raise PreparedStatementInvalid, "missing value for :#{match} in #{statement}"
2009:             end
2010:           end
2011:         end

sanitize_sql_array (ary)

Accepts an array of conditions. The array has each value sanitized and interpolated into the sql statement.

  ["name='%s' and group_id='%s'", "foo'bar", 4]  returns  "name='foo''bar' and group_id='4'"
      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1983
1983:         def sanitize_sql_array(ary)
1984:           statement, *values = ary
1985:           if values.first.is_a?(Hash) and statement =~ /:\w+/
1986:             replace_named_bind_variables(statement, values.first)
1987:           elsif statement.include?('?')
1988:             replace_bind_variables(statement, values)
1989:           else
1990:             statement % values.collect { |value| connection.quote_string(value.to_s) }
1991:           end
1992:         end

sanitize_sql_for_assignment (assignments)

Accepts an array, hash, or string of sql conditions and sanitizes them into a valid SQL fragment for a SET clause.

  { :name => nil, :group_id => 4 }  returns "name = NULL , group_id='4'"
      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1895
1895:         def sanitize_sql_for_assignment(assignments)
1896:           case assignments
1897:             when Array; sanitize_sql_array(assignments)
1898:             when Hash;  sanitize_sql_hash_for_assignment(assignments)
1899:             else        assignments
1900:           end
1901:         end

sanitize_sql_for_conditions (condition)

Accepts an array, hash, or string of sql conditions and sanitizes them into a valid SQL fragment for a WHERE clause.

  ["name='%s' and group_id='%s'", "foo'bar", 4]  returns  "name='foo''bar' and group_id='4'"
  { :name => "foo'bar", :group_id => 4 }  returns "name='foo''bar' and group_id='4'"
  "name='foo''bar' and group_id='4'" returns "name='foo''bar' and group_id='4'"
      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1883
1883:         def sanitize_sql_for_conditions(condition)
1884:           case condition
1885:             when Array; sanitize_sql_array(condition)
1886:             when Hash;  sanitize_sql_hash_for_conditions(condition)
1887:             else        condition
1888:           end
1889:         end

sanitize_sql_hash_for_assignment (attrs)

Sanitizes a hash of attribute/value pairs into SQL conditions for a SET clause.

  { :status => nil, :group_id => 1 }
    # => "status = NULL , group_id = 1"
      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1974
1974:         def sanitize_sql_hash_for_assignment(attrs)
1975:           attrs.map do |attr, value|
1976:             "#{connection.quote_column_name(attr)} = #{quote_bound_value(value)}"
1977:           end.join(', ')
1978:         end

sanitize_sql_hash_for_conditions (attrs)

Sanitizes a hash of attribute/value pairs into SQL conditions for a WHERE clause.

  { :name => "foo'bar", :group_id => 4 }
    # => "name='foo''bar' and group_id= 4"
  { :status => nil, :group_id => [1,2,3] }
    # => "status IS NULL and group_id IN (1,2,3)"
  { :age => 13..18 }
    # => "age BETWEEN 13 AND 18"
  { 'other_records.id' => 7 }
    # => "`other_records`.`id` = 7"

And for value objects on a composed_of relationship:

  { :address => Address.new("123 abc st.", "chicago") }
    # => "address_street='123 abc st.' and address_city='chicago'"
      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1950
1950:         def sanitize_sql_hash_for_conditions(attrs)
1951:           attrs = expand_hash_conditions_for_aggregates(attrs)
1952: 
1953:           conditions = attrs.map do |attr, value|
1954:             attr = attr.to_s
1955: 
1956:             # Extract table name from qualified attribute names.
1957:             if attr.include?('.')
1958:               table_name, attr = attr.split('.', 2)
1959:               table_name = connection.quote_table_name(table_name)
1960:             else
1961:               table_name = quoted_table_name
1962:             end
1963: 
1964:             "#{table_name}.#{connection.quote_column_name(attr)} #{attribute_condition(value)}"
1965:           end.join(' AND ')
1966: 
1967:           replace_bind_variables(conditions, expand_range_bind_variables(attrs.values))
1968:         end

scope (method, key = nil)

Retrieve the scope for the given method and optional key.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1825
1825:         def scope(method, key = nil) #nodoc
1826:           if current_scoped_methods && (scope = current_scoped_methods[method])
1827:             key ? scope[key] : scope
1828:           end
1829:         end

scoped? (method, key = nil)

Test whether the given method and optional key are scoped.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1818
1818:         def scoped?(method, key = nil) #nodoc
1819:           if current_scoped_methods && (scope = current_scoped_methods[method])
1820:             !key || scope.has_key?(key)
1821:           end
1822:         end

set_readonly_option! (options)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2048
2048:         def set_readonly_option!(options) #nodoc
2049:           # Inherit :readonly from finder scope if set.  Otherwise,
2050:           # if :joins is not blank then :readonly defaults to true.
2051:           unless options.has_key?(:readonly)
2052:             if scoped_readonly = scope(:find, :readonly)
2053:               options[:readonly] = scoped_readonly
2054:             elsif !options[:joins].blank? && !options[:select]
2055:               options[:readonly] = true
2056:             end
2057:           end
2058:         end

single_threaded_scoped_methods (

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1836
1836:         def single_threaded_scoped_methods #nodoc
1837:           @scoped_methods ||= []
1838:         end

subclasses (

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1812
1812:         def subclasses #nodoc
1813:           @@subclasses[self] ||= []
1814:           @@subclasses[self] + extra = @@subclasses[self].inject([]) {|list, subclass| list + subclass.subclasses }
1815:         end

thread_safe_scoped_methods (

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1831
1831:         def thread_safe_scoped_methods #nodoc
1832:           scoped_methods = (Thread.current[:scoped_methods] ||= {})
1833:           scoped_methods[self] ||= []
1834:         end

validate_find_options (options)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2044
2044:         def validate_find_options(options) #nodoc
2045:           options.assert_valid_keys(VALID_FIND_OPTIONS)
2046:         end

with_exclusive_scope (method_scoping = {}, &block)

Works like with_scope, but discards any nested properties.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1808
1808:         def with_exclusive_scope(method_scoping = {}, &block)
1809:           with_scope(method_scoping, :overwrite, &block)
1810:         end

with_scope (method_scoping = {}, action = :merge) {|| ...}

Scope parameters to method calls within the block. Takes a hash of method_name => parameters hash. method_name may be :find or :create. :find parameters may include the :conditions, :joins, :include, :offset, :limit, and :readonly options. :create parameters are an attributes hash.

  class Article < ActiveRecord::Base
    def self.create_with_scope
      with_scope(:find => { :conditions => "blog_id = 1" }, :create => { :blog_id => 1 }) do
        find(1) # => SELECT * from articles WHERE blog_id = 1 AND id = 1
        a = create(1)
        a.blog_id # => 1
      end
    end
  end

In nested scopings, all previous parameters are overwritten by the innermost rule, with the exception of :conditions and :include options in :find, which are merged.

  class Article < ActiveRecord::Base
    def self.find_with_scope
      with_scope(:find => { :conditions => "blog_id = 1", :limit => 1 }, :create => { :blog_id => 1 }) do
        with_scope(:find => { :limit => 10})
          find(:all) # => SELECT * from articles WHERE blog_id = 1 LIMIT 10
        end
        with_scope(:find => { :conditions => "author_id = 3" })
          find(:all) # => SELECT * from articles WHERE blog_id = 1 AND author_id = 3 LIMIT 1
        end
      end
    end
  end

You can ignore any previous scopings by using the with_exclusive_scope method.

  class Article < ActiveRecord::Base
    def self.find_with_exclusive_scope
      with_scope(:find => { :conditions => "blog_id = 1", :limit => 1 }) do
        with_exclusive_scope(:find => { :limit => 10 })
          find(:all) # => SELECT * from articles LIMIT 10
        end
      end
    end
  end
      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1756
1756:         def with_scope(method_scoping = {}, action = :merge, &block)
1757:           method_scoping = method_scoping.method_scoping if method_scoping.respond_to?(:method_scoping)
1758: 
1759:           # Dup first and second level of hash (method and params).
1760:           method_scoping = method_scoping.inject({}) do |hash, (method, params)|
1761:             hash[method] = (params == true) ? params : params.dup
1762:             hash
1763:           end
1764: 
1765:           method_scoping.assert_valid_keys([ :find, :create ])
1766: 
1767:           if f = method_scoping[:find]
1768:             f.assert_valid_keys(VALID_FIND_OPTIONS)
1769:             set_readonly_option! f
1770:           end
1771: 
1772:           # Merge scopings
1773:           if action == :merge && current_scoped_methods
1774:             method_scoping = current_scoped_methods.inject(method_scoping) do |hash, (method, params)|
1775:               case hash[method]
1776:                 when Hash
1777:                   if method == :find
1778:                     (hash[method].keys + params.keys).uniq.each do |key|
1779:                       merge = hash[method][key] && params[key] # merge if both scopes have the same key
1780:                       if key == :conditions && merge
1781:                         hash[method][key] = merge_conditions(params[key], hash[method][key])
1782:                       elsif key == :include && merge
1783:                         hash[method][key] = merge_includes(hash[method][key], params[key]).uniq
1784:                       else
1785:                         hash[method][key] = hash[method][key] || params[key]
1786:                       end
1787:                     end
1788:                   else
1789:                     hash[method] = params.merge(hash[method])
1790:                   end
1791:                 else
1792:                   hash[method] = params
1793:               end
1794:               hash
1795:             end
1796:           end
1797: 
1798:           self.scoped_methods << method_scoping
1799: 
1800:           begin
1801:             yield
1802:           ensure
1803:             self.scoped_methods.pop
1804:           end
1805:         end

Private Class Methods


add_conditions! (sql, conditions, scope = :auto)

Adds a sanitized version of conditions to the sql string. Note that the passed-in sql string is changed. The optional scope argument is for the current :find scope.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1528
1528:         def add_conditions!(sql, conditions, scope = :auto)
1529:           scope = scope(:find) if :auto == scope
1530:           conditions = [conditions]
1531:           conditions << scope[:conditions] if scope
1532:           conditions << type_condition if finder_needs_type_condition?
1533:           merged_conditions = merge_conditions(*conditions)
1534:           sql << "WHERE #{merged_conditions} " unless merged_conditions.blank?
1535:         end

add_group! (sql, group, scope = :auto)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1481
1481:         def add_group!(sql, group, scope = :auto)
1482:           if group
1483:             sql << " GROUP BY #{group}"
1484:           else
1485:             scope = scope(:find) if :auto == scope
1486:             if scope && (scoped_group = scope[:group])
1487:               sql << " GROUP BY #{scoped_group}"
1488:             end
1489:           end
1490:         end

add_joins! (sql, options, scope = :auto)

The optional scope argument is for the current :find scope.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1513
1513:         def add_joins!(sql, options, scope = :auto)
1514:           scope = scope(:find) if :auto == scope
1515:           [(scope && scope[:joins]), options[:joins]].each do |join|
1516:             case join
1517:             when Symbol, Hash, Array
1518:               join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, join, nil)
1519:               sql << " #{join_dependency.join_associations.collect { |assoc| assoc.association_join }.join} "
1520:             else
1521:               sql << " #{join} "
1522:             end
1523:           end
1524:         end

add_limit! (sql, options, scope = :auto)

The optional scope argument is for the current :find scope.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1493
1493:         def add_limit!(sql, options, scope = :auto)
1494:           scope = scope(:find) if :auto == scope
1495: 
1496:           if scope
1497:             options[:limit] ||= scope[:limit]
1498:             options[:offset] ||= scope[:offset]
1499:           end
1500: 
1501:           connection.add_limit_offset!(sql, options)
1502:         end

add_lock! (sql, options, scope = :auto)

The optional scope argument is for the current :find scope. The :lock option has precedence over a scoped :lock.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1506
1506:         def add_lock!(sql, options, scope = :auto)
1507:           scope = scope(:find) if :auto == scope
1508:           options = options.reverse_merge(:lock => scope[:lock]) if scope
1509:           connection.add_lock!(sql, options)
1510:         end

add_order! (sql, order, scope = :auto)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1470
1470:         def add_order!(sql, order, scope = :auto)
1471:           scope = scope(:find) if :auto == scope
1472:           scoped_order = scope[:order] if scope
1473:           if order
1474:             sql << " ORDER BY #{order}"
1475:             sql << ", #{scoped_order}" if scoped_order
1476:           else
1477:             sql << " ORDER BY #{scoped_order}" if scoped_order
1478:           end
1479:         end

all_attributes_exists? (attribute_names)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1661
1661:         def all_attributes_exists?(attribute_names)
1662:           attribute_names = expand_attribute_names_for_aggregates(attribute_names)
1663:           attribute_names.all? { |name| column_methods_hash.include?(name.to_sym) }
1664:         end

attribute_condition (argument)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1666
1666:         def attribute_condition(argument)
1667:           case argument
1668:             when nil   then "IS ?"
1669:             when Array, ActiveRecord::Associations::AssociationCollection then "IN (?)"
1670:             when Range then "BETWEEN ? AND ?"
1671:             else            "= ?"
1672:           end
1673:         end

clear_all_cached_connections! ()

     # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 157
157:         def clear_all_cached_connections!
158:           if @@allow_concurrency
159:             @@active_connections.each_value do |connection_hash_for_thread|
160:               connection_hash_for_thread.each_value {|conn| conn.disconnect! }
161:               connection_hash_for_thread.clear
162:             end
163:           else
164:             @@active_connections.each_value {|conn| conn.disconnect! }
165:           end
166:           @@active_connections.clear          
167:         end

clear_cache! (cache, thread_id = nil, &block)

     # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 127
127:         def clear_cache!(cache, thread_id = nil, &block)
128:           if cache
129:             if @@allow_concurrency
130:               thread_id ||= Thread.current.object_id
131:               thread_cache, cache = cache, cache[thread_id]
132:               return unless cache
133:             end
134: 
135:             cache.each(&block) if block_given?
136:             cache.clear
137:           end
138:         ensure
139:           if thread_cache && @@allow_concurrency
140:             thread_cache.delete(thread_id)
141:           end
142:         end

construct_attributes_from_arguments (attribute_names, arguments)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1640
1640:         def construct_attributes_from_arguments(attribute_names, arguments)
1641:           attributes = {}
1642:           attribute_names.each_with_index { |name, idx| attributes[name] = arguments[idx] }
1643:           attributes
1644:         end

construct_finder_sql (options)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1423
1423:         def construct_finder_sql(options)
1424:           scope = scope(:find)
1425:           sql  = "SELECT #{(scope && scope[:select]) || options[:select] || (options[:joins] && quoted_table_name + '.*') || '*'} "
1426:           sql << "FROM #{(scope && scope[:from]) || options[:from] || quoted_table_name} "
1427: 
1428:           add_joins!(sql, options, scope)
1429:           add_conditions!(sql, options[:conditions], scope)
1430: 
1431:           add_group!(sql, options[:group], scope)
1432:           add_order!(sql, options[:order], scope)
1433:           add_limit!(sql, options, scope)
1434:           add_lock!(sql, options, scope)
1435: 
1436:           sql
1437:         end

define_attr_method (name, value=nil, &block)

Defines an "attribute" method (like inheritance_column or table_name). 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 will be aliased, with the new name being prefixed with "original_". This allows the new method to access the original value.

Example:

  class A < ActiveRecord::Base
    define_attr_method :primary_key, "sysid"
    define_attr_method( :inheritance_column ) do
      original_inheritance_column + "_id"
    end
  end
      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1702
1702:         def define_attr_method(name, value=nil, &block)
1703:           sing = class << self; self; end
1704:           sing.send :alias_method, "original_#{name}", name
1705:           if block_given?
1706:             sing.send :define_method, name, &block
1707:           else
1708:             # use eval instead of a block to work around a memory leak in dev
1709:             # mode in fcgi
1710:             sing.class_eval "def #{name}; #{value.to_s.inspect}; end"
1711:           end
1712:         end

determine_finder (match)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1628
1628:         def determine_finder(match)
1629:           match.captures.first == 'all_by' ? :find_every : :find_initial
1630:         end

determine_instantiator (match)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1632
1632:         def determine_instantiator(match)
1633:           match.captures.first == 'initialize' ? :new : :create
1634:         end

expand_attribute_names_for_aggregates (attribute_names)

Similar in purpose to expand_hash_conditions_for_aggregates.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1647
1647:         def expand_attribute_names_for_aggregates(attribute_names)
1648:           expanded_attribute_names = []
1649:           attribute_names.each do |attribute_name|
1650:             unless (aggregation = reflect_on_aggregation(attribute_name.to_sym)).nil?
1651:               aggregate_mapping(aggregation).each do |field_attr, aggregate_attr|
1652:                 expanded_attribute_names << field_attr
1653:               end
1654:             else
1655:               expanded_attribute_names << attribute_name
1656:             end
1657:           end
1658:           expanded_attribute_names
1659:         end

expand_id_conditions (id_or_conditions)

Interpret Array and Hash as conditions and anything else as an id.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1676
1676:         def expand_id_conditions(id_or_conditions)
1677:           case id_or_conditions
1678:             when Array, Hash then id_or_conditions
1679:             else sanitize_sql(primary_key => id_or_conditions)
1680:           end
1681:         end

extract_attribute_names_from_match (match)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1636
1636:         def extract_attribute_names_from_match(match)
1637:           match.captures.last.split('_and_')
1638:         end

find_every (options)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1296
1296:         def find_every(options)
1297:           include_associations = merge_includes(scope(:find, :include), options[:include])
1298: 
1299:           if include_associations.any? && references_eager_loaded_tables?(options)
1300:             records = find_with_associations(options)
1301:           else
1302:             records = find_by_sql(construct_finder_sql(options))
1303:             if include_associations.any?
1304:               preload_associations(records, include_associations)
1305:             end
1306:           end
1307: 
1308:           records.each { |record| record.readonly! } if options[:readonly]
1309: 
1310:           records
1311:         end

find_from_ids (ids, options)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1313
1313:         def find_from_ids(ids, options)
1314:           expects_array = ids.first.kind_of?(Array)
1315:           return ids.first if expects_array && ids.first.empty?
1316: 
1317:           ids = ids.flatten.compact.uniq
1318: 
1319:           case ids.size
1320:             when 0
1321:               raise RecordNotFound, "Couldn't find #{name} without an ID"
1322:             when 1
1323:               result = find_one(ids.first, options)
1324:               expects_array ? [ result ] : result
1325:             else
1326:               find_some(ids, options)
1327:           end
1328:         end

find_initial (options)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1262
1262:         def find_initial(options)
1263:           options.update(:limit => 1) unless options[:include]
1264:           find_every(options).first
1265:         end

find_last (options)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1267
1267:         def find_last(options)
1268:           order = options[:order]
1269: 
1270:           if order
1271:             order = reverse_sql_order(order)
1272:           elsif !scoped?(:find, :order)
1273:             order = "#{table_name}.#{primary_key} DESC"
1274:           end
1275: 
1276:           if scoped?(:find, :order)
1277:             scoped_order = reverse_sql_order(scope(:find, :order))
1278:             scoped_methods.select { |s| s[:find].update(:order => scoped_order) }
1279:           end
1280:           
1281:           find_initial(options.merge({ :order => order }))
1282:         end

find_one (id, options)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1330
1330:         def find_one(id, options)
1331:           conditions = " AND (#{sanitize_sql(options[:conditions])})" if options[:conditions]
1332:           options.update :conditions => "#{quoted_table_name}.#{connection.quote_column_name(primary_key)} = #{quote_value(id,columns_hash[primary_key])}#{conditions}"
1333: 
1334:           # Use find_every(options).first since the primary key condition
1335:           # already ensures we have a single record. Using find_initial adds
1336:           # a superfluous :limit => 1.
1337:           if result = find_every(options).first
1338:             result
1339:           else
1340:             raise RecordNotFound, "Couldn't find #{name} with ID=#{id}#{conditions}"
1341:           end
1342:         end

find_some (ids, options)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1344
1344:         def find_some(ids, options)
1345:           conditions = " AND (#{sanitize_sql(options[:conditions])})" if options[:conditions]
1346:           ids_list   = ids.map { |id| quote_value(id,columns_hash[primary_key]) }.join(',')
1347:           options.update :conditions => "#{quoted_table_name}.#{connection.quote_column_name(primary_key)} IN (#{ids_list})#{conditions}"
1348: 
1349:           result = find_every(options)
1350: 
1351:           # Determine expected size from limit and offset, not just ids.size.
1352:           expected_size =
1353:             if options[:limit] && ids.size > options[:limit]
1354:               options[:limit]
1355:             else
1356:               ids.size
1357:             end
1358: 
1359:           # 11 ids with limit 3, offset 9 should give 2 results.
1360:           if options[:offset] && (ids.size - options[:offset] < expected_size)
1361:             expected_size = ids.size - options[:offset]
1362:           end
1363: 
1364:           if result.size == expected_size
1365:             result
1366:           else
1367:             raise RecordNotFound, "Couldn't find all #{name.pluralize} with IDs (#{ids_list})#{conditions} (found #{result.size} results, but was looking for #{expected_size})"
1368:           end
1369:         end

instantiate (record)

Finder methods must instantiate through this method to work with the single-table inheritance model that makes it possible to create objects of different types from the same table.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1374
1374:         def instantiate(record)
1375:           object =
1376:             if subclass_name = record[inheritance_column]
1377:               # No type given.
1378:               if subclass_name.empty?
1379:                 allocate
1380: 
1381:               else
1382:                 # Ignore type if no column is present since it was probably
1383:                 # pulled in from a sloppy join.
1384:                 unless columns_hash.include?(inheritance_column)
1385:                   allocate
1386: 
1387:                 else
1388:                   begin
1389:                     compute_type(subclass_name).allocate
1390:                   rescue NameError
1391:                     raise SubclassNotFound,
1392:                       "The single-table inheritance mechanism failed to locate the subclass: '#{record[inheritance_column]}'. " +
1393:                       "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " +
1394:                       "Please rename this column if you didn't intend it to be used for storing the inheritance class " +
1395:                       "or overwrite #{self.to_s}.inheritance_column to use another column for that information."
1396:                   end
1397:                 end
1398:               end
1399:             else
1400:               allocate
1401:             end
1402: 
1403:           object.instance_variable_set("@attributes", record)
1404:           object.instance_variable_set("@attributes_cache", Hash.new)
1405: 
1406:           if object.respond_to_without_attributes?(:after_find)
1407:             object.send(:callback, :after_find)
1408:           end
1409: 
1410:           if object.respond_to_without_attributes?(:after_initialize)
1411:             object.send(:callback, :after_initialize)
1412:           end
1413: 
1414:           object
1415:         end

merge_conditions (*conditions)

Merges conditions so that the result is a valid condition

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1445
1445:         def merge_conditions(*conditions)
1446:           segments = []
1447: 
1448:           conditions.each do |condition|
1449:             unless condition.blank?
1450:               sql = sanitize_sql(condition)
1451:               segments << sql unless sql.blank?
1452:             end
1453:           end
1454: 
1455:           "(#{segments.join(') AND (')})" unless segments.empty?
1456:         end

merge_includes (first, second)

Merges includes so that the result is a valid include

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1440
1440:         def merge_includes(first, second)
1441:          (safe_to_array(first) + safe_to_array(second)).uniq
1442:         end

method_missing (method_id, *arguments)

Enables dynamic finders like find_by_user_name(user_name) and find_by_user_name_and_password(user_name, password) that are turned into find(:first, :conditions => ["user_name = ?", user_name]) and find(:first, :conditions => ["user_name = ? AND password = ?", user_name, password]) respectively. Also works for find(:all) by using find_all_by_amount(50) that is turned into find(:all, :conditions => ["amount = ?", 50]).

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) 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 attempts to use it do not run through method_missing.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1565
1565:         def method_missing(method_id, *arguments)
1566:           if match = /^find_(all_by|by)_([_a-zA-Z]\w*)$/.match(method_id.to_s)
1567:             finder = determine_finder(match)
1568: 
1569:             attribute_names = extract_attribute_names_from_match(match)
1570:             super unless all_attributes_exists?(attribute_names)
1571: 
1572:             self.class_eval %{
1573:               def self.#{method_id}(*args)
1574:                 options = args.extract_options!
1575:                 attributes = construct_attributes_from_arguments([:#{attribute_names.join(',:')}], args)
1576:                 finder_options = { :conditions => attributes }
1577:                 validate_find_options(options)
1578:                 set_readonly_option!(options)
1579: 
1580:                 if options[:conditions]
1581:                   with_scope(:find => finder_options) do
1582:                     ActiveSupport::Deprecation.silence { send(:#{finder}, options) }
1583:                   end
1584:                 else
1585:                   ActiveSupport::Deprecation.silence { send(:#{finder}, options.merge(finder_options)) }
1586:                 end
1587:               end
1588:             }, __FILE__, __LINE__
1589:             send(method_id, *arguments)
1590:           elsif match = /^find_or_(initialize|create)_by_([_a-zA-Z]\w*)$/.match(method_id.to_s)
1591:             instantiator = determine_instantiator(match)
1592:             attribute_names = extract_attribute_names_from_match(match)
1593:             super unless all_attributes_exists?(attribute_names)
1594: 
1595:             self.class_eval %{
1596:               def self.#{method_id}(*args)
1597:                 guard_protected_attributes = false
1598:                 
1599:                 if args[0].is_a?(Hash)
1600:                   guard_protected_attributes = true
1601:                   attributes = args[0].with_indifferent_access
1602:                   find_attributes = attributes.slice(*[:#{attribute_names.join(',:')}])
1603:                 else
1604:                   find_attributes = attributes = construct_attributes_from_arguments([:#{attribute_names.join(',:')}], args)
1605:                 end
1606: 
1607:                 options = { :conditions => find_attributes }
1608:                 set_readonly_option!(options)
1609: 
1610:                 record = find_initial(options)
1611:                  
1612:                  if record.nil?
1613:                   record = self.new { |r| r.send(:attributes=, attributes, guard_protected_attributes) }
1614:                   #{'yield(record) if block_given?'}
1615:                   #{'record.save' if instantiator == :create}
1616:                   record
1617:                 else
1618:                   record
1619:                 end
1620:               end
1621:             }, __FILE__, __LINE__
1622:             send(method_id, *arguments)
1623:           else
1624:             super
1625:           end
1626:         end

parse_sqlite_config! (config)

    # File vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb, line 28
28:         def parse_sqlite_config!(config)
29:           config[:database] ||= config[:dbfile]
30:           # Require database.
31:           unless config[:database]
32:             raise ArgumentError, "No database file specified. Missing argument: database"
33:           end
34: 
35:           # Allow database path relative to RAILS_ROOT, but only if
36:           # the database path is not the special path that tells
37:           # Sqlite to build a database only in memory.
38:           if Object.const_defined?(:RAILS_ROOT) && ':memory:' != config[:database]
39:             config[:database] = File.expand_path(config[:database], RAILS_ROOT)
40:           end
41:         end

quoted_table_name ()

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2625
2625:       def self.quoted_table_name
2626:         self.connection.quote_table_name(self.table_name)
2627:       end

remove_stale_cached_threads! (cache, &block)

Remove stale threads from the cache.

     # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 145
145:         def remove_stale_cached_threads!(cache, &block)
146:           stale = Set.new(cache.keys)
147: 
148:           Thread.list.each do |thread|
149:             stale.delete(thread.object_id) if thread.alive?
150:           end
151: 
152:           stale.each do |thread_id|
153:             clear_cache!(cache, thread_id, &block)
154:           end
155:         end

reverse_sql_order (order_query)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1284
1284:         def reverse_sql_order(order_query)
1285:           reversed_query = order_query.split(/,/).each { |s|
1286:             if s.match(/\s(asc|ASC)$/)
1287:               s.gsub!(/\s(asc|ASC)$/, ' DESC')
1288:             elsif s.match(/\s(desc|DESC)$/)
1289:               s.gsub!(/\s(desc|DESC)$/, ' ASC')
1290:             elsif !s.match(/\s(asc|ASC|desc|DESC)$/) 
1291:               s.concat(' DESC')
1292:             end
1293:           }.join(',')
1294:         end

safe_to_array (o)

Object#to_a is deprecated, though it does have the desired behavior

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1459
1459:         def safe_to_array(o)
1460:           case o
1461:           when NilClass
1462:             []
1463:           when Array
1464:             o
1465:           else
1466:             [o]
1467:           end
1468:         end

type_condition ()

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1537
1537:         def type_condition
1538:           quoted_inheritance_column = connection.quote_column_name(inheritance_column)
1539:           type_condition = subclasses.inject("#{quoted_table_name}.#{quoted_inheritance_column} = '#{name.demodulize}' ") do |condition, subclass|
1540:             condition << "OR #{quoted_table_name}.#{quoted_inheritance_column} = '#{subclass.name.demodulize}' "
1541:           end
1542: 
1543:           " (#{type_condition}) "
1544:         end

type_name_with_module (type_name)

Nest the type name in the same module as this class. Bar is "MyApp::Business::Bar" relative to MyApp::Business::Foo

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1419
1419:         def type_name_with_module(type_name)
1420:           (/^::/ =~ type_name) ? type_name : "#{parent.name}::#{type_name}"
1421:         end

undecorated_table_name (class_name = base_class.name)

Guesses the table name, but does not decorate it with prefix and suffix information.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 1547
1547:         def undecorated_table_name(class_name = base_class.name)
1548:           table_name = Inflector.underscore(Inflector.demodulize(class_name))
1549:           table_name = Inflector.pluralize(table_name) if pluralize_table_names
1550:           table_name
1551:         end

Public Instance Methods


== (comparison_object)

Returns true if the comparison_object is the same object, or is of the same type and has the same id.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2353
2353:       def ==(comparison_object)
2354:         comparison_object.equal?(self) ||
2355:           (comparison_object.instance_of?(self.class) &&
2356:             comparison_object.id == id &&
2357:             !comparison_object.new_record?)
2358:       end

[] (attr_name)

Returns the value of the attribute identified by attr_name after it has been typecast (for example, "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). (Alias for the protected read_attribute method).

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2270
2270:       def [](attr_name)
2271:         read_attribute(attr_name)
2272:       end

[]= (attr_name, value)

Updates the attribute identified by attr_name with the specified value. (Alias for the protected write_attribute method).

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2276
2276:       def []=(attr_name, value)
2277:         write_attribute(attr_name, value)
2278:       end

attribute_for_inspect (attr_name)

Format attributes nicely for inspect.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2318
2318:       def attribute_for_inspect(attr_name)
2319:         value = read_attribute(attr_name)
2320: 
2321:         if value.is_a?(String) && value.length > 50
2322:           "#{value[0..50]}...".inspect
2323:         elsif value.is_a?(Date) || value.is_a?(Time)
2324:           %("#{value.to_s(:db)}")
2325:         else
2326:           value.inspect
2327:         end
2328:       end

attribute_names ()

Returns an array of names for the attributes available on this object sorted alphabetically.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2343
2343:       def attribute_names
2344:         @attributes.keys.sort
2345:       end

attribute_present? (attribute)

Returns true if the specified attribute has been set by the user or by a database load and is neither nil nor empty? (the latter only applies to objects that respond to empty?, most notably Strings).

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2332
2332:       def attribute_present?(attribute)
2333:         value = read_attribute(attribute)
2334:         !value.blank?
2335:       end

attributes (options = nil)

Returns a hash of all the attributes with their names as keys and the values of the attributes as values.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2302
2302:       def attributes(options = nil)
2303:         self.attribute_names.inject({}) do |attrs, name|
2304:           attrs[name] = read_attribute(name)
2305:           attrs
2306:         end
2307:       end

attributes= (new_attributes, guard_protected_attributes = true)

Allows you to set all the attributes at once by passing in a hash with keys 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.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2285
2285:       def attributes=(new_attributes, guard_protected_attributes = true)
2286:         return if new_attributes.nil?
2287:         attributes = new_attributes.dup
2288:         attributes.stringify_keys!
2289: 
2290:         multi_parameter_attributes = []
2291:         attributes = remove_attributes_protected_from_mass_assignment(attributes) if guard_protected_attributes
2292: 
2293:         attributes.each do |k, v|
2294:           k.include?("(") ? multi_parameter_attributes << [ k, v ] : send(k + "=", v)
2295:         end
2296: 
2297:         assign_multiparameter_attributes(multi_parameter_attributes)
2298:       end

attributes_before_type_cast ()

Returns a hash of attributes before typecasting and deserialization.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2310
2310:       def attributes_before_type_cast
2311:         self.attribute_names.inject({}) do |attrs, name|
2312:           attrs[name] = read_attribute_before_type_cast(name)
2313:           attrs
2314:         end
2315:       end

becomes (klass)

Returns an instance of the specified klass with the attributes of the current record. This is mostly useful in relation to single-table inheritance structures where you want a subclass to appear as the superclass. This can be used along with record identification in Action Pack to allow, say, Client < Company to do something like render :partial => @client.becomes(Company) to render that instance using the companies/company partial instead of clients/client.

Note: The new instance will share a link to the same attributes as the original class. So any change to the attributes in either instance will affect the other.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2188
2188:       def becomes(klass)
2189:         returning klass.new do |became|
2190:           became.instance_variable_set("@attributes", @attributes)
2191:           became.instance_variable_set("@attributes_cache", @attributes_cache)
2192:           became.instance_variable_set("@new_record", new_record?)
2193:         end
2194:       end

cache_key ()

Returns a cache key that can be used to identify this record. Examples:

  Product.new.cache_key     # => "products/new"
  Product.find(5).cache_key # => "products/5" (updated_at not available)
  Person.find(5).cache_key  # => "people/5-20071224150000" (updated_at available)
      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2107
2107:       def cache_key
2108:         case 
2109:         when new_record?
2110:           "#{self.class.name.tableize}/new"
2111:         when self[:updated_at]
2112:           "#{self.class.name.tableize}/#{id}-#{updated_at.to_s(:number)}"
2113:         else
2114:           "#{self.class.name.tableize}/#{id}"
2115:         end
2116:       end

clone ()

Returns a clone of the record that hasn‘t been assigned an id yet and is treated as a new record. Note that this is a "shallow" clone: it copies the object‘s attributes only, not its associations. The extent of a "deep" clone is application-specific and is therefore left to the application to implement according to its need.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2173
2173:       def clone
2174:         attrs = clone_attributes(:read_attribute_before_type_cast)
2175:         attrs.delete(self.class.primary_key)
2176:         record = self.class.new
2177:         record.send :instance_variable_set, '@attributes', attrs
2178:         record
2179:       end

column_for_attribute (name)

Returns the column object for the named attribute.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2348
2348:       def column_for_attribute(name)
2349:         self.class.columns_hash[name.to_s]
2350:       end

connection ()

Returns the connection currently associated with the class. This can also be used to "borrow" the connection to do database work that isn‘t easily done without going straight to SQL.

     # File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb, line 173
173:     def connection
174:       self.class.connection
175:     end

decrement (attribute, by = 1)

Initializes the attribute to zero if nil and subtracts the value passed as by (default is one). Only makes sense for number-based attributes. Returns self.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2231
2231:       def decrement(attribute, by = 1)
2232:         self[attribute] ||= 0
2233:         self[attribute] -= by
2234:         self
2235:       end

decrement! (attribute, by = 1)

Decrements the attribute and saves the record. Note: Updates made with this method aren‘t subjected to validation checks

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2239
2239:       def decrement!(attribute, by = 1)
2240:         decrement(attribute, by).update_attribute(attribute, self[attribute])
2241:       end

destroy ()

Deletes the record in the database and freezes this instance to reflect that no changes should be made (since they can‘t be persisted).

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2156
2156:       def destroy
2157:         unless new_record?
2158:           connection.delete "DELETE FROM \#{self.class.quoted_table_name}\nWHERE \#{connection.quote_column_name(self.class.primary_key)} = \#{quoted_id}\n", "#{self.class.name} Destroy"
2159:         end
2160: 
2161:         freeze
2162:       end

eql? (comparison_object)

Delegates to ==

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2361
2361:       def eql?(comparison_object)
2362:         self == (comparison_object)
2363:       end

freeze ()

Freeze the attributes hash such that associations are still accessible, even on destroyed records.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2372
2372:       def freeze
2373:         @attributes.freeze; self
2374:       end

frozen? ()

Returns true if the attributes hash has been frozen.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2377
2377:       def frozen?
2378:         @attributes.frozen?
2379:       end

has_attribute? (attr_name)

Returns true if the given attribute is in the attributes hash

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2338
2338:       def has_attribute?(attr_name)
2339:         @attributes.has_key?(attr_name.to_s)
2340:       end

hash ()

Delegates 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) ]
      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2367
2367:       def hash
2368:         id.hash
2369:       end

id ()

A model instance‘s primary key is always available as model.id whether you name it the default ‘id’ or set it to something else.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2086
2086:       def id
2087:         attr_name = self.class.primary_key
2088:         column = column_for_attribute(attr_name)
2089: 
2090:         self.class.send(:define_read_method, :id, attr_name, column)
2091:         # now that the method exists, call it
2092:         self.send attr_name.to_sym
2093: 
2094:       end

id= (value)

Sets the primary ID.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2127
2127:       def id=(value)
2128:         write_attribute(self.class.primary_key, value)
2129:       end

id_before_type_cast (

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2118
2118:       def id_before_type_cast #nodoc
2119:         read_attribute_before_type_cast(self.class.primary_key)
2120:       end

increment (attribute, by = 1)

Initializes the attribute to zero if nil and adds the value passed as by (default is one). Only makes sense for number-based attributes. Returns self.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2218
2218:       def increment(attribute, by = 1)
2219:         self[attribute] ||= 0
2220:         self[attribute] += by
2221:         self
2222:       end

increment! (attribute, by = 1)

Increments the attribute and saves the record. Note: Updates made with this method aren‘t subjected to validation checks

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2226
2226:       def increment!(attribute, by = 1)
2227:         increment(attribute, by).update_attribute(attribute, self[attribute])
2228:       end

inspect ()

Returns the contents of the record as a nicely formatted string.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2393
2393:       def inspect
2394:         attributes_as_nice_string = self.class.column_names.collect { |name|
2395:           if has_attribute?(name) || new_record?
2396:             "#{name}: #{attribute_for_inspect(name)}"
2397:           end
2398:         }.compact.join(", ")
2399:         "#<#{self.class} #{attributes_as_nice_string}>"
2400:       end

new_record? ()

Returns true if this object hasn‘t been saved yet — that is, a record for the object doesn‘t exist yet.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2132
2132:       def new_record?
2133:         defined?(@new_record) && @new_record
2134:       end

quoted_id (

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2122
2122:       def quoted_id #nodoc
2123:         quote_value(id, column_for_attribute(self.class.primary_key))
2124:       end

readonly! ()

Marks this record as read only.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2388
2388:       def readonly!
2389:         @readonly = true
2390:       end

readonly? ()

Returns true if the record is read only. Records loaded through joins with piggy-back attributes will be marked as read only since they cannot be saved.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2383
2383:       def readonly?
2384:         defined?(@readonly) && @readonly == true
2385:       end

reload (options = nil)

Reloads the attributes of this object from the database. The optional options argument is passed to find when reloading so you may do e.g. record.reload(:lock => true) to reload the same record with an exclusive row lock.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2259
2259:       def reload(options = nil)
2260:         clear_aggregation_cache
2261:         clear_association_cache
2262:         @attributes.update(self.class.find(self.id, options).instance_variable_get('@attributes'))
2263:         @attributes_cache = {}
2264:         self
2265:       end

save ()

  • No record exists: Creates a new record with values matching those of the object attributes.
  • A record does exist: Updates the record with values matching those of the object attributes.

Note: If your model specifies any validations then the method declaration dynamically changes to:

  save(perform_validation=true)

Calling save(false) saves the model without running validations. See ActiveRecord::Validations for more information.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2144
2144:       def save
2145:         create_or_update
2146:       end

save! ()

Attempts to save the record, but instead of just returning false if it couldn‘t happen, it raises a RecordNotSaved exception

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2150
2150:       def save!
2151:         create_or_update || raise(RecordNotSaved)
2152:       end

to_param ()

Enables Active Record objects to be used as URL parameters in Action Pack automatically.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2097
2097:       def to_param
2098:         # We can't use alias_method here, because method 'id' optimizes itself on the fly.
2099:         (id = self.id) ? id.to_s : nil # Be sure to stringify the id for routes
2100:       end

toggle (attribute)

Turns an attribute that‘s currently true into false and vice versa. Returns self.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2244
2244:       def toggle(attribute)
2245:         self[attribute] = !send("#{attribute}?")
2246:         self
2247:       end

toggle! (attribute)

Toggles the attribute and saves the record. Note: Updates made with this method aren‘t subjected to validation checks

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2251
2251:       def toggle!(attribute)
2252:         toggle(attribute).update_attribute(attribute, self[attribute])
2253:       end

update_attribute (name, value)

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 aren‘t subjected to validation checks. Hence, attributes can be updated even if the full object isn‘t valid.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2199
2199:       def update_attribute(name, value)
2200:         send(name.to_s + '=', value)
2201:         save
2202:       end

update_attributes (attributes)

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.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2206
2206:       def update_attributes(attributes)
2207:         self.attributes = attributes
2208:         save
2209:       end

update_attributes! (attributes)

Updates an object just like Base.update_attributes but calls save! instead of save so an exception is raised if the record is invalid.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2212
2212:       def update_attributes!(attributes)
2213:         self.attributes = attributes
2214:         save!
2215:       end

Private Instance Methods


assign_multiparameter_attributes (pairs)

Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done by calling new on the column type or aggregation type (through composed_of) object with these parameters. So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the parentheses to have the parameters typecasted before they‘re used in the constructor. Use i for Fixnum, f for Float, s for String, and a for Array. If all the values for a given attribute are empty, the attribute will be set to nil.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2543
2543:       def assign_multiparameter_attributes(pairs)
2544:         execute_callstack_for_multiparameter_attributes(
2545:           extract_callstack_for_multiparameter_attributes(pairs)
2546:         )
2547:       end

attributes_from_column_definition ()

Initializes the attributes array with keys matching the columns from the linked table and the values matching the corresponding default value of that column, so that a new instance, or one populated from a passed-in Hash, still has all the attributes that instances loaded from the database would.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2530
2530:       def attributes_from_column_definition
2531:         self.class.columns.inject({}) do |attributes, column|
2532:           attributes[column.name] = column.default unless column.name == self.class.primary_key
2533:           attributes
2534:         end
2535:       end

attributes_protected_by_default ()

The primary key and inheritance column can never be set by mass-assignment for security reasons.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2496
2496:       def attributes_protected_by_default
2497:         default = [ self.class.primary_key, self.class.inheritance_column ]
2498:         default << 'id' unless self.class.primary_key.eql? 'id'
2499:         default
2500:       end

attributes_with_quotes (include_primary_key = true, include_readonly_attributes = true, attribute_names = @attributes.keys)

Returns a copy of the attributes hash where all the values have been safely quoted for use in an SQL statement.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2504
2504:       def attributes_with_quotes(include_primary_key = true, include_readonly_attributes = true, attribute_names = @attributes.keys)
2505:         quoted = {}
2506:         connection = self.class.connection
2507:         attribute_names.each do |name|
2508:           if column = column_for_attribute(name)
2509:             quoted[name] = connection.quote(read_attribute(name), column) unless !include_primary_key && column.primary
2510:           end
2511:         end
2512:         include_readonly_attributes ? quoted : remove_readonly_attributes(quoted)
2513:       end

clone_attribute_value (reader_method, attribute_name)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2652
2652:       def clone_attribute_value(reader_method, attribute_name)
2653:         value = send(reader_method, attribute_name)
2654:         value.duplicable? ? value.clone : value
2655:       rescue TypeError, NoMethodError
2656:         value
2657:       end

clone_attributes (reader_method = :read_attribute, attributes = {})

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2645
2645:       def clone_attributes(reader_method = :read_attribute, attributes = {})
2646:         self.attribute_names.inject(attributes) do |attrs, name|
2647:           attrs[name] = clone_attribute_value(reader_method, name)
2648:           attrs
2649:         end
2650:       end

comma_pair_list (hash)

Returns a comma-separated pair list, like "key1 = val1, key2 = val2".

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2614
2614:       def comma_pair_list(hash)
2615:         hash.inject([]) { |list, pair| list << "#{pair.first} = #{pair.last}" }.join(", ")
2616:       end

convert_number_column_value (value)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2456
2456:       def convert_number_column_value(value)
2457:         case value
2458:           when FalseClass; 0
2459:           when TrueClass;  1
2460:           when '';         nil
2461:           else value
2462:         end
2463:       end

create ()

Creates a record with values matching those of the instance attributes and returns its id.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2424
2424:       def create
2425:         if self.id.nil? && connection.prefetch_primary_key?(self.class.table_name)
2426:           self.id = connection.next_sequence_value(self.class.sequence_name)
2427:         end
2428: 
2429:         quoted_attributes = attributes_with_quotes
2430: 
2431:         statement = if quoted_attributes.empty?
2432:           connection.empty_insert_statement(self.class.table_name)
2433:         else
2434:           "INSERT INTO #{self.class.quoted_table_name} " +
2435:           "(#{quoted_column_names.join(', ')}) " +
2436:           "VALUES(#{quoted_attributes.values.join(', ')})"
2437:         end
2438: 
2439:         self.id = connection.insert(statement, "#{self.class.name} Create",
2440:           self.class.primary_key, self.id, self.class.sequence_name)
2441: 
2442:         @new_record = false
2443:         id
2444:       end

create_or_update ()

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2403
2403:       def create_or_update
2404:         raise ReadOnlyRecord if readonly?
2405:         result = new_record? ? create : update
2406:         result != false
2407:       end

ensure_proper_type ()

Sets the attribute used for single table inheritance to this class name if this is not the ActiveRecord descendent. Considering the hierarchy Reply < Message < ActiveRecord, this makes it possible to do Reply.new without having to set Reply = "Reply" yourself. No such attribute would be set for objects of the Message class in that example.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2450
2450:       def ensure_proper_type
2451:         unless self.class.descends_from_active_record?
2452:           write_attribute(self.class.inheritance_column, Inflector.demodulize(self.class.name))
2453:         end
2454:       end

execute_callstack_for_multiparameter_attributes (callstack)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2557
2557:       def execute_callstack_for_multiparameter_attributes(callstack)
2558:         errors = []
2559:         callstack.each do |name, values|
2560:           klass = (self.class.reflect_on_aggregation(name.to_sym) || column_for_attribute(name)).klass
2561:           if values.empty?
2562:             send(name + "=", nil)
2563:           else
2564:             begin
2565:               value = if Time == klass
2566:                 instantiate_time_object(name, values)
2567:               elsif Date == klass
2568:                 begin
2569:                   Date.new(*values)
2570:                 rescue ArgumentError => ex # if Date.new raises an exception on an invalid date
2571:                   instantiate_time_object(name, values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates
2572:                 end
2573:               else
2574:                 klass.new(*values)
2575:               end
2576: 
2577:               send(name + "=", value)
2578:             rescue => ex
2579:               errors << AttributeAssignmentError.new("error on assignment #{values.inspect} to #{name}", ex, name)
2580:             end
2581:           end
2582:         end
2583:         unless errors.empty?
2584:           raise MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes"
2585:         end
2586:       end

extract_callstack_for_multiparameter_attributes (pairs)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2588
2588:       def extract_callstack_for_multiparameter_attributes(pairs)
2589:         attributes = { }
2590: 
2591:         for pair in pairs
2592:           multiparameter_name, value = pair
2593:           attribute_name = multiparameter_name.split("(").first
2594:           attributes[attribute_name] = [] unless attributes.include?(attribute_name)
2595: 
2596:           unless value.empty?
2597:             attributes[attribute_name] <<
2598:               [ find_parameter_position(multiparameter_name), type_cast_attribute_value(multiparameter_name, value) ]
2599:           end
2600:         end
2601: 
2602:         attributes.each { |name, values| attributes[name] = values.sort_by{ |v| v.first }.collect { |v| v.last } }
2603:       end

find_parameter_position (multiparameter_name)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2609
2609:       def find_parameter_position(multiparameter_name)
2610:         multiparameter_name.scan(/\(([0-9]*).*\)/).first.first
2611:       end

instantiate_time_object (name, values)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2549
2549:       def instantiate_time_object(name, values)
2550:         if Time.zone && self.class.time_zone_aware_attributes && !self.class.skip_time_zone_conversion_for_attributes.include?(name.to_sym)
2551:           Time.zone.local(*values)
2552:         else
2553:           Time.time_with_datetime_fallback(@@default_timezone, *values)
2554:         end
2555:       end

interpolate_sql (sql, record = nil)

Interpolate custom sql string in instance context. Optional record argument is meant for custom insert_sql.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2522
2522:       def interpolate_sql(sql, record = nil)
2523:         instance_eval("%@#{sql.gsub('@', '\@')}@")
2524:       end

object_from_yaml (string)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2640
2640:       def object_from_yaml(string)
2641:         return string unless string.is_a?(String)
2642:         YAML::load(string) rescue string
2643:       end

quote_columns (quoter, hash)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2629
2629:       def quote_columns(quoter, hash)
2630:         hash.inject({}) do |quoted, (name, value)|
2631:           quoted[quoter.quote_column_name(name)] = value
2632:           quoted
2633:         end
2634:       end

quote_value (value, column = nil)

Quote strings appropriately for SQL statements.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2516
2516:       def quote_value(value, column = nil)
2517:         self.class.connection.quote(value, column)
2518:       end

quoted_column_names (attributes = attributes_with_quotes)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2618
2618:       def quoted_column_names(attributes = attributes_with_quotes)
2619:         connection = self.class.connection
2620:         attributes.keys.collect do |column_name|
2621:           connection.quote_column_name(column_name)
2622:         end
2623:       end

quoted_comma_pair_list (quoter, hash)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2636
2636:       def quoted_comma_pair_list(quoter, hash)
2637:         comma_pair_list(quote_columns(quoter, hash))
2638:       end

remove_attributes_protected_from_mass_assignment (attributes)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2465
2465:       def remove_attributes_protected_from_mass_assignment(attributes)
2466:         safe_attributes =
2467:           if self.class.accessible_attributes.nil? && self.class.protected_attributes.nil?
2468:             attributes.reject { |key, value| attributes_protected_by_default.include?(key.gsub(/\(.+/, "")) }
2469:           elsif self.class.protected_attributes.nil?
2470:             attributes.reject { |key, value| !self.class.accessible_attributes.include?(key.gsub(/\(.+/, "")) || attributes_protected_by_default.include?(key.gsub(/\(.+/, "")) }
2471:           elsif self.class.accessible_attributes.nil?
2472:             attributes.reject { |key, value| self.class.protected_attributes.include?(key.gsub(/\(.+/,"")) || attributes_protected_by_default.include?(key.gsub(/\(.+/, "")) }
2473:           else
2474:             raise "Declare either attr_protected or attr_accessible for #{self.class}, but not both."
2475:           end
2476: 
2477:         removed_attributes = attributes.keys - safe_attributes.keys
2478: 
2479:         if removed_attributes.any?
2480:           logger.debug "WARNING: Can't mass-assign these protected attributes: #{removed_attributes.join(', ')}"
2481:         end
2482: 
2483:         safe_attributes
2484:       end

remove_readonly_attributes (attributes)

Removes attributes which have been marked as readonly.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2487
2487:       def remove_readonly_attributes(attributes)
2488:         unless self.class.readonly_attributes.nil?
2489:           attributes.delete_if { |key, value| self.class.readonly_attributes.include?(key.gsub(/\(.+/,"")) }
2490:         else
2491:           attributes
2492:         end
2493:       end

type_cast_attribute_value (multiparameter_name, value)

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2605
2605:       def type_cast_attribute_value(multiparameter_name, value)
2606:         multiparameter_name =~ /\([0-9]*([a-z])\)/ ? value.send("to_" + $1) : value
2607:       end

update (attribute_names = @attributes.keys)

Updates the associated record with values matching those of the instance attributes. Returns the number of affected rows.

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2411
2411:       def update(attribute_names = @attributes.keys)
2412:         quoted_attributes = attributes_with_quotes(false, false, attribute_names)
2413:         return 0 if quoted_attributes.empty?
2414:         connection.update(
2415:           "UPDATE #{self.class.quoted_table_name} " +
2416:           "SET #{quoted_comma_pair_list(connection, quoted_attributes)} " +
2417:           "WHERE #{connection.quote_column_name(self.class.primary_key)} = #{quote_value(id)}",
2418:           "#{self.class.name} Update"
2419:         )
2420:       end