PageRenderTime 49ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/rails/activerecord/lib/active_record/base.rb

https://github.com/brownjohnf/instiki
Ruby | 3220 lines | 1575 code | 280 blank | 1365 comment | 163 complexity | 07303c415857b83811136e83861e582c MD5 | raw file
Possible License(s): ISC, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. require 'yaml'
  2. require 'set'
  3. require 'active_support/core_ext/class/attribute'
  4. module ActiveRecord #:nodoc:
  5. # Generic Active Record exception class.
  6. class ActiveRecordError < StandardError
  7. end
  8. # Raised when the single-table inheritance mechanism fails to locate the subclass
  9. # (for example due to improper usage of column that +inheritance_column+ points to).
  10. class SubclassNotFound < ActiveRecordError #:nodoc:
  11. end
  12. # Raised when an object assigned to an association has an incorrect type.
  13. #
  14. # class Ticket < ActiveRecord::Base
  15. # has_many :patches
  16. # end
  17. #
  18. # class Patch < ActiveRecord::Base
  19. # belongs_to :ticket
  20. # end
  21. #
  22. # # Comments are not patches, this assignment raises AssociationTypeMismatch.
  23. # @ticket.patches << Comment.new(:content => "Please attach tests to your patch.")
  24. class AssociationTypeMismatch < ActiveRecordError
  25. end
  26. # Raised when unserialized object's type mismatches one specified for serializable field.
  27. class SerializationTypeMismatch < ActiveRecordError
  28. end
  29. # Raised when adapter not specified on connection (or configuration file <tt>config/database.yml</tt> misses adapter field).
  30. class AdapterNotSpecified < ActiveRecordError
  31. end
  32. # Raised when Active Record cannot find database adapter specified in <tt>config/database.yml</tt> or programmatically.
  33. class AdapterNotFound < ActiveRecordError
  34. end
  35. # Raised when connection to the database could not been established (for example when <tt>connection=</tt> is given a nil object).
  36. class ConnectionNotEstablished < ActiveRecordError
  37. end
  38. # Raised when Active Record cannot find record by given id or set of ids.
  39. class RecordNotFound < ActiveRecordError
  40. end
  41. # Raised by ActiveRecord::Base.save! and ActiveRecord::Base.create! methods when record cannot be
  42. # saved because record is invalid.
  43. class RecordNotSaved < ActiveRecordError
  44. end
  45. # Raised when SQL statement cannot be executed by the database (for example, it's often the case for MySQL when Ruby driver used is too old).
  46. class StatementInvalid < ActiveRecordError
  47. end
  48. # Raised when number of bind variables in statement given to <tt>:condition</tt> key (for example, when using +find+ method)
  49. # does not match number of expected variables.
  50. #
  51. # For example, in
  52. #
  53. # Location.find :all, :conditions => ["lat = ? AND lng = ?", 53.7362]
  54. #
  55. # two placeholders are given but only one variable to fill them.
  56. class PreparedStatementInvalid < ActiveRecordError
  57. end
  58. # Raised on attempt to save stale record. Record is stale when it's being saved in another query after
  59. # instantiation, for example, when two users edit the same wiki page and one starts editing and saves
  60. # the page before the other.
  61. #
  62. # Read more about optimistic locking in ActiveRecord::Locking module RDoc.
  63. class StaleObjectError < ActiveRecordError
  64. end
  65. # Raised when association is being configured improperly or
  66. # user tries to use offset and limit together with has_many or has_and_belongs_to_many associations.
  67. class ConfigurationError < ActiveRecordError
  68. end
  69. # Raised on attempt to update record that is instantiated as read only.
  70. class ReadOnlyRecord < ActiveRecordError
  71. end
  72. # ActiveRecord::Transactions::ClassMethods.transaction uses this exception
  73. # to distinguish a deliberate rollback from other exceptional situations.
  74. # Normally, raising an exception will cause the +transaction+ method to rollback
  75. # the database transaction *and* pass on the exception. But if you raise an
  76. # ActiveRecord::Rollback exception, then the database transaction will be rolled back,
  77. # without passing on the exception.
  78. #
  79. # For example, you could do this in your controller to rollback a transaction:
  80. #
  81. # class BooksController < ActionController::Base
  82. # def create
  83. # Book.transaction do
  84. # book = Book.new(params[:book])
  85. # book.save!
  86. # if today_is_friday?
  87. # # The system must fail on Friday so that our support department
  88. # # won't be out of job. We silently rollback this transaction
  89. # # without telling the user.
  90. # raise ActiveRecord::Rollback, "Call tech support!"
  91. # end
  92. # end
  93. # # ActiveRecord::Rollback is the only exception that won't be passed on
  94. # # by ActiveRecord::Base.transaction, so this line will still be reached
  95. # # even on Friday.
  96. # redirect_to root_url
  97. # end
  98. # end
  99. class Rollback < ActiveRecordError
  100. end
  101. # Raised when attribute has a name reserved by Active Record (when attribute has name of one of Active Record instance methods).
  102. class DangerousAttributeError < ActiveRecordError
  103. end
  104. # Raised when you've tried to access a column which wasn't loaded by your finder.
  105. # Typically this is because <tt>:select</tt> has been specified.
  106. class MissingAttributeError < NoMethodError
  107. end
  108. # Raised when unknown attributes are supplied via mass assignment.
  109. class UnknownAttributeError < NoMethodError
  110. end
  111. # Raised when an error occurred while doing a mass assignment to an attribute through the
  112. # <tt>attributes=</tt> method. The exception has an +attribute+ property that is the name of the
  113. # offending attribute.
  114. class AttributeAssignmentError < ActiveRecordError
  115. attr_reader :exception, :attribute
  116. def initialize(message, exception, attribute)
  117. @exception = exception
  118. @attribute = attribute
  119. @message = message
  120. end
  121. end
  122. # Raised when there are multiple errors while doing a mass assignment through the +attributes+
  123. # method. The exception has an +errors+ property that contains an array of AttributeAssignmentError
  124. # objects, each corresponding to the error while assigning to an attribute.
  125. class MultiparameterAssignmentErrors < ActiveRecordError
  126. attr_reader :errors
  127. def initialize(errors)
  128. @errors = errors
  129. end
  130. end
  131. # Active Record objects don't specify their attributes directly, but rather infer them from the table definition with
  132. # which they're linked. Adding, removing, and changing attributes and their type is done directly in the database. Any change
  133. # is instantly reflected in the Active Record objects. The mapping that binds a given Active Record class to a certain
  134. # database table will happen automatically in most common cases, but can be overwritten for the uncommon ones.
  135. #
  136. # See the mapping rules in table_name and the full example in link:files/README.html for more insight.
  137. #
  138. # == Creation
  139. #
  140. # Active Records accept constructor parameters either in a hash or as a block. The hash method is especially useful when
  141. # you're receiving the data from somewhere else, like an HTTP request. It works like this:
  142. #
  143. # user = User.new(:name => "David", :occupation => "Code Artist")
  144. # user.name # => "David"
  145. #
  146. # You can also use block initialization:
  147. #
  148. # user = User.new do |u|
  149. # u.name = "David"
  150. # u.occupation = "Code Artist"
  151. # end
  152. #
  153. # And of course you can just create a bare object and specify the attributes after the fact:
  154. #
  155. # user = User.new
  156. # user.name = "David"
  157. # user.occupation = "Code Artist"
  158. #
  159. # == Conditions
  160. #
  161. # Conditions can either be specified as a string, array, or hash representing the WHERE-part of an SQL statement.
  162. # The array form is to be used when the condition input is tainted and requires sanitization. The string form can
  163. # be used for statements that don't involve tainted data. The hash form works much like the array form, except
  164. # only equality and range is possible. Examples:
  165. #
  166. # class User < ActiveRecord::Base
  167. # def self.authenticate_unsafely(user_name, password)
  168. # find(:first, :conditions => "user_name = '#{user_name}' AND password = '#{password}'")
  169. # end
  170. #
  171. # def self.authenticate_safely(user_name, password)
  172. # find(:first, :conditions => [ "user_name = ? AND password = ?", user_name, password ])
  173. # end
  174. #
  175. # def self.authenticate_safely_simply(user_name, password)
  176. # find(:first, :conditions => { :user_name => user_name, :password => password })
  177. # end
  178. # end
  179. #
  180. # The <tt>authenticate_unsafely</tt> method inserts the parameters directly into the query and is thus susceptible to SQL-injection
  181. # attacks if the <tt>user_name</tt> and +password+ parameters come directly from an HTTP request. The <tt>authenticate_safely</tt> and
  182. # <tt>authenticate_safely_simply</tt> both will sanitize the <tt>user_name</tt> and +password+ before inserting them in the query,
  183. # which will ensure that an attacker can't escape the query and fake the login (or worse).
  184. #
  185. # When using multiple parameters in the conditions, it can easily become hard to read exactly what the fourth or fifth
  186. # question mark is supposed to represent. In those cases, you can resort to named bind variables instead. That's done by replacing
  187. # the question marks with symbols and supplying a hash with values for the matching symbol keys:
  188. #
  189. # Company.find(:first, :conditions => [
  190. # "id = :id AND name = :name AND division = :division AND created_at > :accounting_date",
  191. # { :id => 3, :name => "37signals", :division => "First", :accounting_date => '2005-01-01' }
  192. # ])
  193. #
  194. # Similarly, a simple hash without a statement will generate conditions based on equality with the SQL AND
  195. # operator. For instance:
  196. #
  197. # Student.find(:all, :conditions => { :first_name => "Harvey", :status => 1 })
  198. # Student.find(:all, :conditions => params[:student])
  199. #
  200. # A range may be used in the hash to use the SQL BETWEEN operator:
  201. #
  202. # Student.find(:all, :conditions => { :grade => 9..12 })
  203. #
  204. # An array may be used in the hash to use the SQL IN operator:
  205. #
  206. # Student.find(:all, :conditions => { :grade => [9,11,12] })
  207. #
  208. # == Overwriting default accessors
  209. #
  210. # All column values are automatically available through basic accessors on the Active Record object, but sometimes you
  211. # want to specialize this behavior. This can be done by overwriting the default accessors (using the same
  212. # name as the attribute) and calling <tt>read_attribute(attr_name)</tt> and <tt>write_attribute(attr_name, value)</tt> to actually change things.
  213. # Example:
  214. #
  215. # class Song < ActiveRecord::Base
  216. # # Uses an integer of seconds to hold the length of the song
  217. #
  218. # def length=(minutes)
  219. # write_attribute(:length, minutes.to_i * 60)
  220. # end
  221. #
  222. # def length
  223. # read_attribute(:length) / 60
  224. # end
  225. # end
  226. #
  227. # You can alternatively use <tt>self[:attribute]=(value)</tt> and <tt>self[:attribute]</tt> instead of <tt>write_attribute(:attribute, value)</tt> and
  228. # <tt>read_attribute(:attribute)</tt> as a shorter form.
  229. #
  230. # == Attribute query methods
  231. #
  232. # In addition to the basic accessors, query methods are also automatically available on the Active Record object.
  233. # Query methods allow you to test whether an attribute value is present.
  234. #
  235. # For example, an Active Record User with the <tt>name</tt> attribute has a <tt>name?</tt> method that you can call
  236. # to determine whether the user has a name:
  237. #
  238. # user = User.new(:name => "David")
  239. # user.name? # => true
  240. #
  241. # anonymous = User.new(:name => "")
  242. # anonymous.name? # => false
  243. #
  244. # == Accessing attributes before they have been typecasted
  245. #
  246. # Sometimes you want to be able to read the raw attribute data without having the column-determined typecast run its course first.
  247. # That can be done by using the <tt><attribute>_before_type_cast</tt> accessors that all attributes have. For example, if your Account model
  248. # has a <tt>balance</tt> attribute, you can call <tt>account.balance_before_type_cast</tt> or <tt>account.id_before_type_cast</tt>.
  249. #
  250. # This is especially useful in validation situations where the user might supply a string for an integer field and you want to display
  251. # the original string back in an error message. Accessing the attribute normally would typecast the string to 0, which isn't what you
  252. # want.
  253. #
  254. # == Dynamic attribute-based finders
  255. #
  256. # Dynamic attribute-based finders are a cleaner way of getting (and/or creating) objects by simple queries without turning to SQL. They work by
  257. # appending the name of an attribute to <tt>find_by_</tt>, <tt>find_last_by_</tt>, or <tt>find_all_by_</tt>, so you get finders like <tt>Person.find_by_user_name</tt>,
  258. # <tt>Person.find_all_by_last_name</tt>, and <tt>Payment.find_by_transaction_id</tt>. So instead of writing
  259. # <tt>Person.find(:first, :conditions => ["user_name = ?", user_name])</tt>, you just do <tt>Person.find_by_user_name(user_name)</tt>.
  260. # And instead of writing <tt>Person.find(:all, :conditions => ["last_name = ?", last_name])</tt>, you just do <tt>Person.find_all_by_last_name(last_name)</tt>.
  261. #
  262. # It's also possible to use multiple attributes in the same find by separating them with "_and_", so you get finders like
  263. # <tt>Person.find_by_user_name_and_password</tt> or even <tt>Payment.find_by_purchaser_and_state_and_country</tt>. So instead of writing
  264. # <tt>Person.find(:first, :conditions => ["user_name = ? AND password = ?", user_name, password])</tt>, you just do
  265. # <tt>Person.find_by_user_name_and_password(user_name, password)</tt>.
  266. #
  267. # It's even possible to use all the additional parameters to find. For example, the full interface for <tt>Payment.find_all_by_amount</tt>
  268. # is actually <tt>Payment.find_all_by_amount(amount, options)</tt>. And the full interface to <tt>Person.find_by_user_name</tt> is
  269. # actually <tt>Person.find_by_user_name(user_name, options)</tt>. So you could call <tt>Payment.find_all_by_amount(50, :order => "created_on")</tt>.
  270. # Also you may call <tt>Payment.find_last_by_amount(amount, options)</tt> returning the last record matching that amount and options.
  271. #
  272. # The same dynamic finder style can be used to create the object if it doesn't already exist. This dynamic finder is called with
  273. # <tt>find_or_create_by_</tt> 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:
  274. #
  275. # # No 'Summer' tag exists
  276. # Tag.find_or_create_by_name("Summer") # equal to Tag.create(:name => "Summer")
  277. #
  278. # # Now the 'Summer' tag does exist
  279. # Tag.find_or_create_by_name("Summer") # equal to Tag.find_by_name("Summer")
  280. #
  281. # # Now 'Bob' exist and is an 'admin'
  282. # User.find_or_create_by_name('Bob', :age => 40) { |u| u.admin = true }
  283. #
  284. # Use the <tt>find_or_initialize_by_</tt> finder if you want to return a new record without saving it first. Protected attributes won't be set unless they are given in a block. For example:
  285. #
  286. # # No 'Winter' tag exists
  287. # winter = Tag.find_or_initialize_by_name("Winter")
  288. # winter.new_record? # true
  289. #
  290. # To find by a subset of the attributes to be used for instantiating a new object, pass a hash instead of
  291. # a list of parameters. For example:
  292. #
  293. # Tag.find_or_create_by_name(:name => "rails", :creator => current_user)
  294. #
  295. # That will either find an existing tag named "rails", or create a new one while setting the user that created it.
  296. #
  297. # == Saving arrays, hashes, and other non-mappable objects in text columns
  298. #
  299. # 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+.
  300. # This makes it possible to store arrays, hashes, and other non-mappable objects without doing any additional work. Example:
  301. #
  302. # class User < ActiveRecord::Base
  303. # serialize :preferences
  304. # end
  305. #
  306. # user = User.create(:preferences => { "background" => "black", "display" => large })
  307. # User.find(user.id).preferences # => { "background" => "black", "display" => large }
  308. #
  309. # You can also specify a class option as the second parameter that'll raise an exception if a serialized object is retrieved as a
  310. # descendant of a class not in the hierarchy. Example:
  311. #
  312. # class User < ActiveRecord::Base
  313. # serialize :preferences, Hash
  314. # end
  315. #
  316. # user = User.create(:preferences => %w( one two three ))
  317. # User.find(user.id).preferences # raises SerializationTypeMismatch
  318. #
  319. # == Single table inheritance
  320. #
  321. # Active Record allows inheritance by storing the name of the class in a column that by default is named "type" (can be changed
  322. # by overwriting <tt>Base.inheritance_column</tt>). This means that an inheritance looking like this:
  323. #
  324. # class Company < ActiveRecord::Base; end
  325. # class Firm < Company; end
  326. # class Client < Company; end
  327. # class PriorityClient < Client; end
  328. #
  329. # When you do <tt>Firm.create(:name => "37signals")</tt>, this record will be saved in the companies table with type = "Firm". You can then
  330. # fetch this row again using <tt>Company.find(:first, "name = '37signals'")</tt> and it will return a Firm object.
  331. #
  332. # 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
  333. # like normal subclasses with no special magic for differentiating between them or reloading the right type with find.
  334. #
  335. # Note, all the attributes for all the cases are kept in the same table. Read more:
  336. # http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
  337. #
  338. # == Connection to multiple databases in different models
  339. #
  340. # Connections are usually created through ActiveRecord::Base.establish_connection and retrieved by ActiveRecord::Base.connection.
  341. # All classes inheriting from ActiveRecord::Base will use this connection. But you can also set a class-specific connection.
  342. # For example, if Course is an ActiveRecord::Base, but resides in a different database, you can just say <tt>Course.establish_connection</tt>
  343. # and Course and all of its subclasses will use this connection instead.
  344. #
  345. # This feature is implemented by keeping a connection pool in ActiveRecord::Base that is a Hash indexed by the class. If a connection is
  346. # requested, the retrieve_connection method will go up the class-hierarchy until a connection is found in the connection pool.
  347. #
  348. # == Exceptions
  349. #
  350. # * ActiveRecordError - Generic error class and superclass of all other errors raised by Active Record.
  351. # * AdapterNotSpecified - The configuration hash used in <tt>establish_connection</tt> didn't include an
  352. # <tt>:adapter</tt> key.
  353. # * AdapterNotFound - The <tt>:adapter</tt> key used in <tt>establish_connection</tt> specified a non-existent adapter
  354. # (or a bad spelling of an existing one).
  355. # * AssociationTypeMismatch - The object assigned to the association wasn't of the type specified in the association definition.
  356. # * SerializationTypeMismatch - The serialized object wasn't of the class specified as the second parameter.
  357. # * ConnectionNotEstablished+ - No connection has been established. Use <tt>establish_connection</tt> before querying.
  358. # * RecordNotFound - No record responded to the +find+ method. Either the row with the given ID doesn't exist
  359. # or the row didn't meet the additional restrictions. Some +find+ calls do not raise this exception to signal
  360. # nothing was found, please check its documentation for further details.
  361. # * StatementInvalid - The database server rejected the SQL statement. The precise error is added in the message.
  362. # * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the
  363. # <tt>attributes=</tt> method. The +errors+ property of this exception contains an array of AttributeAssignmentError
  364. # objects that should be inspected to determine which attributes triggered the errors.
  365. # * AttributeAssignmentError - An error occurred while doing a mass assignment through the <tt>attributes=</tt> method.
  366. # You can inspect the +attribute+ property of the exception object to determine which attribute triggered the error.
  367. #
  368. # *Note*: The attributes listed are class-level attributes (accessible from both the class and instance level).
  369. # So it's possible to assign a logger to the class through <tt>Base.logger=</tt> which will then be used by all
  370. # instances in the current object space.
  371. class Base
  372. ##
  373. # :singleton-method:
  374. # Accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then passed
  375. # on to any new database connections made and which can be retrieved on both a class and instance level by calling +logger+.
  376. cattr_accessor :logger, :instance_writer => false
  377. def self.inherited(child) #:nodoc:
  378. @@subclasses[self] ||= []
  379. @@subclasses[self] << child
  380. super
  381. end
  382. def self.reset_subclasses #:nodoc:
  383. nonreloadables = []
  384. subclasses.each do |klass|
  385. unless ActiveSupport::Dependencies.autoloaded? klass
  386. nonreloadables << klass
  387. next
  388. end
  389. klass.instance_variables.each { |var| klass.send(:remove_instance_variable, var) }
  390. klass.instance_methods(false).each { |m| klass.send :undef_method, m }
  391. end
  392. @@subclasses = {}
  393. nonreloadables.each { |klass| (@@subclasses[klass.superclass] ||= []) << klass }
  394. end
  395. @@subclasses = {}
  396. ##
  397. # :singleton-method:
  398. # Contains the database configuration - as is typically stored in config/database.yml -
  399. # as a Hash.
  400. #
  401. # For example, the following database.yml...
  402. #
  403. # development:
  404. # adapter: sqlite3
  405. # database: db/development.sqlite3
  406. #
  407. # production:
  408. # adapter: sqlite3
  409. # database: db/production.sqlite3
  410. #
  411. # ...would result in ActiveRecord::Base.configurations to look like this:
  412. #
  413. # {
  414. # 'development' => {
  415. # 'adapter' => 'sqlite3',
  416. # 'database' => 'db/development.sqlite3'
  417. # },
  418. # 'production' => {
  419. # 'adapter' => 'sqlite3',
  420. # 'database' => 'db/production.sqlite3'
  421. # }
  422. # }
  423. cattr_accessor :configurations, :instance_writer => false
  424. @@configurations = {}
  425. ##
  426. # :singleton-method:
  427. # Accessor for the prefix type that will be prepended to every primary key column name. The options are :table_name and
  428. # :table_name_with_underscore. If the first is specified, the Product class will look for "productid" instead of "id" as
  429. # the primary column. If the latter is specified, the Product class will look for "product_id" instead of "id". Remember
  430. # that this is a global setting for all Active Records.
  431. cattr_accessor :primary_key_prefix_type, :instance_writer => false
  432. @@primary_key_prefix_type = nil
  433. ##
  434. # :singleton-method:
  435. # Accessor for the name of the prefix string to prepend to every table name. So if set to "basecamp_", all
  436. # table names will be named like "basecamp_projects", "basecamp_people", etc. This is a convenient way of creating a namespace
  437. # for tables in a shared database. By default, the prefix is the empty string.
  438. #
  439. # If you are organising your models within modules you can add a prefix to the models within a namespace by defining
  440. # a singleton method in the parent module called table_name_prefix which returns your chosen prefix.
  441. cattr_accessor :table_name_prefix, :instance_writer => false
  442. @@table_name_prefix = ""
  443. ##
  444. # :singleton-method:
  445. # Works like +table_name_prefix+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp",
  446. # "people_basecamp"). By default, the suffix is the empty string.
  447. cattr_accessor :table_name_suffix, :instance_writer => false
  448. @@table_name_suffix = ""
  449. ##
  450. # :singleton-method:
  451. # Indicates whether table names should be the pluralized versions of the corresponding class names.
  452. # If true, the default table name for a Product class will be +products+. If false, it would just be +product+.
  453. # See table_name for the full rules on table/class naming. This is true, by default.
  454. cattr_accessor :pluralize_table_names, :instance_writer => false
  455. @@pluralize_table_names = true
  456. ##
  457. # :singleton-method:
  458. # Determines whether to use ANSI codes to colorize the logging statements committed by the connection adapter. These colors
  459. # make it much easier to overview things during debugging (when used through a reader like +tail+ and on a black background), but
  460. # may complicate matters if you use software like syslog. This is true, by default.
  461. cattr_accessor :colorize_logging, :instance_writer => false
  462. @@colorize_logging = true
  463. ##
  464. # :singleton-method:
  465. # Determines whether to use Time.local (using :local) or Time.utc (using :utc) when pulling dates and times from the database.
  466. # This is set to :local by default.
  467. cattr_accessor :default_timezone, :instance_writer => false
  468. @@default_timezone = :local
  469. ##
  470. # :singleton-method:
  471. # Specifies the format to use when dumping the database schema with Rails'
  472. # Rakefile. If :sql, the schema is dumped as (potentially database-
  473. # specific) SQL statements. If :ruby, the schema is dumped as an
  474. # ActiveRecord::Schema file which can be loaded into any database that
  475. # supports migrations. Use :ruby if you want to have different database
  476. # adapters for, e.g., your development and test environments.
  477. cattr_accessor :schema_format , :instance_writer => false
  478. @@schema_format = :ruby
  479. ##
  480. # :singleton-method:
  481. # Specify whether or not to use timestamps for migration numbers
  482. cattr_accessor :timestamped_migrations , :instance_writer => false
  483. @@timestamped_migrations = true
  484. # Determine whether to store the full constant name including namespace when using STI
  485. class_attribute :store_full_sti_class
  486. self.store_full_sti_class = false
  487. # Stores the default scope for the class
  488. class_inheritable_accessor :default_scoping, :instance_writer => false
  489. self.default_scoping = []
  490. class << self # Class methods
  491. # Find operates with four different retrieval approaches:
  492. #
  493. # * 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]).
  494. # If no record can be found for all of the listed ids, then RecordNotFound will be raised.
  495. # * Find first - This will return the first record matched by the options used. These options can either be specific
  496. # conditions or merely an order. If no record can be matched, +nil+ is returned. Use
  497. # <tt>Model.find(:first, *args)</tt> or its shortcut <tt>Model.first(*args)</tt>.
  498. # * Find last - This will return the last record matched by the options used. These options can either be specific
  499. # conditions or merely an order. If no record can be matched, +nil+ is returned. Use
  500. # <tt>Model.find(:last, *args)</tt> or its shortcut <tt>Model.last(*args)</tt>.
  501. # * Find all - This will return all the records matched by the options used.
  502. # If no records are found, an empty array is returned. Use
  503. # <tt>Model.find(:all, *args)</tt> or its shortcut <tt>Model.all(*args)</tt>.
  504. #
  505. # All approaches accept an options hash as their last parameter.
  506. #
  507. # ==== Parameters
  508. #
  509. # * <tt>:conditions</tt> - An SQL fragment like "administrator = 1", <tt>[ "user_name = ?", username ]</tt>, or <tt>["user_name = :user_name", { :user_name => user_name }]</tt>. See conditions in the intro.
  510. # * <tt>:order</tt> - An SQL fragment like "created_at DESC, name".
  511. # * <tt>:group</tt> - An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause.
  512. # * <tt>:having</tt> - Combined with +:group+ this can be used to filter the records that a <tt>GROUP BY</tt> returns. Uses the <tt>HAVING</tt> SQL-clause.
  513. # * <tt>:limit</tt> - An integer determining the limit on the number of rows that should be returned.
  514. # * <tt>:offset</tt> - An integer determining the offset from where the rows should be fetched. So at 5, it would skip rows 0 through 4.
  515. # * <tt>:joins</tt> - Either an SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id" (rarely needed),
  516. # named associations in the same form used for the <tt>:include</tt> option, which will perform an <tt>INNER JOIN</tt> on the associated table(s),
  517. # or an array containing a mixture of both strings and named associations.
  518. # 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.
  519. # Pass <tt>:readonly => false</tt> to override.
  520. # * <tt>:include</tt> - Names associations that should be loaded alongside. The symbols named refer
  521. # to already defined associations. See eager loading under Associations.
  522. # * <tt>:select</tt> - By default, this is "*" as in "SELECT * FROM", but can be changed if you, for example, want to do a join but not
  523. # include the joined columns. Takes a string with the SELECT SQL fragment (e.g. "id, name").
  524. # * <tt>:from</tt> - By default, this is the table name of the class, but can be changed to an alternate table name (or even the name
  525. # of a database view).
  526. # * <tt>:readonly</tt> - Mark the returned records read-only so they cannot be saved or updated.
  527. # * <tt>:lock</tt> - An SQL fragment like "FOR UPDATE" or "LOCK IN SHARE MODE".
  528. # <tt>:lock => true</tt> gives connection's default exclusive lock, usually "FOR UPDATE".
  529. #
  530. # ==== Examples
  531. #
  532. # # find by id
  533. # Person.find(1) # returns the object for ID = 1
  534. # Person.find(1, 2, 6) # returns an array for objects with IDs in (1, 2, 6)
  535. # Person.find([7, 17]) # returns an array for objects with IDs in (7, 17)
  536. # Person.find([1]) # returns an array for the object with ID = 1
  537. # Person.find(1, :conditions => "administrator = 1", :order => "created_on DESC")
  538. #
  539. # Note that returned records may not be in the same order as the ids you
  540. # provide since database rows are unordered. Give an explicit <tt>:order</tt>
  541. # to ensure the results are sorted.
  542. #
  543. # ==== Examples
  544. #
  545. # # find first
  546. # Person.find(:first) # returns the first object fetched by SELECT * FROM people
  547. # Person.find(:first, :conditions => [ "user_name = ?", user_name])
  548. # Person.find(:first, :conditions => [ "user_name = :u", { :u => user_name }])
  549. # Person.find(:first, :order => "created_on DESC", :offset => 5)
  550. #
  551. # # find last
  552. # Person.find(:last) # returns the last object fetched by SELECT * FROM people
  553. # Person.find(:last, :conditions => [ "user_name = ?", user_name])
  554. # Person.find(:last, :order => "created_on DESC", :offset => 5)
  555. #
  556. # # find all
  557. # Person.find(:all) # returns an array of objects for all the rows fetched by SELECT * FROM people
  558. # Person.find(:all, :conditions => [ "category IN (?)", categories], :limit => 50)
  559. # Person.find(:all, :conditions => { :friends => ["Bob", "Steve", "Fred"] }
  560. # Person.find(:all, :offset => 10, :limit => 10)
  561. # Person.find(:all, :include => [ :account, :friends ])
  562. # Person.find(:all, :group => "category")
  563. #
  564. # Example for find with a lock: Imagine two concurrent transactions:
  565. # each will read <tt>person.visits == 2</tt>, add 1 to it, and save, resulting
  566. # in two saves of <tt>person.visits = 3</tt>. By locking the row, the second
  567. # transaction has to wait until the first is finished; we get the
  568. # expected <tt>person.visits == 4</tt>.
  569. #
  570. # Person.transaction do
  571. # person = Person.find(1, :lock => true)
  572. # person.visits += 1
  573. # person.save!
  574. # end
  575. def find(*args)
  576. options = args.extract_options!
  577. validate_find_options(options)
  578. set_readonly_option!(options)
  579. case args.first
  580. when :first then find_initial(options)
  581. when :last then find_last(options)
  582. when :all then find_every(options)
  583. else find_from_ids(args, options)
  584. end
  585. end
  586. # A convenience wrapper for <tt>find(:first, *args)</tt>. You can pass in all the
  587. # same arguments to this method as you can to <tt>find(:first)</tt>.
  588. def first(*args)
  589. find(:first, *args)
  590. end
  591. # A convenience wrapper for <tt>find(:last, *args)</tt>. You can pass in all the
  592. # same arguments to this method as you can to <tt>find(:last)</tt>.
  593. def last(*args)
  594. find(:last, *args)
  595. end
  596. # This is an alias for find(:all). You can pass in all the same arguments to this method as you can
  597. # to find(:all)
  598. def all(*args)
  599. find(:all, *args)
  600. end
  601. # Executes a custom SQL query against your database and returns all the results. The results will
  602. # be returned as an array with columns requested encapsulated as attributes of the model you call
  603. # this method from. If you call <tt>Product.find_by_sql</tt> then the results will be returned in
  604. # a Product object with the attributes you specified in the SQL query.
  605. #
  606. # If you call a complicated SQL query which spans multiple tables the columns specified by the
  607. # SELECT will be attributes of the model, whether or not they are columns of the corresponding
  608. # table.
  609. #
  610. # The +sql+ parameter is a full SQL query as a string. It will be called as is, there will be
  611. # no database agnostic conversions performed. This should be a last resort because using, for example,
  612. # MySQL specific terms will lock you to using that particular database engine or require you to
  613. # change your call if you switch engines.
  614. #
  615. # ==== Examples
  616. # # A simple SQL query spanning multiple tables
  617. # Post.find_by_sql "SELECT p.title, c.author FROM posts p, comments c WHERE p.id = c.post_id"
  618. # > [#<Post:0x36bff9c @attributes={"title"=>"Ruby Meetup", "first_name"=>"Quentin"}>, ...]
  619. #
  620. # # You can use the same string replacement techniques as you can with ActiveRecord#find
  621. # Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]
  622. # > [#<Post:0x36bff9c @attributes={"first_name"=>"The Cheap Man Buys Twice"}>, ...]
  623. def find_by_sql(sql)
  624. connection.select_all(sanitize_sql(sql), "#{name} Load").collect! { |record| instantiate(record) }
  625. end
  626. # Returns true if a record exists in the table that matches the +id+ or
  627. # conditions given, or false otherwise. The argument can take five forms:
  628. #
  629. # * Integer - Finds the record with this primary key.
  630. # * String - Finds the record with a primary key corresponding to this
  631. # string (such as <tt>'5'</tt>).
  632. # * Array - Finds the record that matches these +find+-style conditions
  633. # (such as <tt>['color = ?', 'red']</tt>).
  634. # * Hash - Finds the record that matches these +find+-style conditions
  635. # (such as <tt>{:color => 'red'}</tt>).
  636. # * No args - Returns false if the table is empty, true otherwise.
  637. #
  638. # For more information about specifying conditions as a Hash or Array,
  639. # see the Conditions section in the introduction to ActiveRecord::Base.
  640. #
  641. # Note: You can't pass in a condition as a string (like <tt>name =
  642. # 'Jamie'</tt>), since it would be sanitized and then queried against
  643. # the primary key column, like <tt>id = 'name = \'Jamie\''</tt>.
  644. #
  645. # ==== Examples
  646. # Person.exists?(5)
  647. # Person.exists?('5')
  648. # Person.exists?(:name => "David")
  649. # Person.exists?(['name LIKE ?', "%#{query}%"])
  650. # Person.exists?
  651. def exists?(id_or_conditions = {})
  652. find_initial(
  653. :select => "#{quoted_table_name}.#{primary_key}",
  654. :conditions => expand_id_conditions(id_or_conditions)) ? true : false
  655. end
  656. # Creates an object (or multiple objects) and saves it to the database, if validations pass.
  657. # The resulting object is returned whether the object was saved successfully to the database or not.
  658. #
  659. # The +attributes+ parameter can be either be a Hash or an Array of Hashes. These Hashes describe the
  660. # attributes on the objects that are to be created.
  661. #
  662. # ==== Examples
  663. # # Create a single new object
  664. # User.create(:first_name => 'Jamie')
  665. #
  666. # # Create an Array of new objects
  667. # User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }])
  668. #
  669. # # Create a single object and pass it into a block to set other attributes.
  670. # User.create(:first_name => 'Jamie') do |u|
  671. # u.is_admin = false
  672. # end
  673. #
  674. # # Creating an Array of new objects using a block, where the block is executed for each object:
  675. # User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }]) do |u|
  676. # u.is_admin = false
  677. # end
  678. def create(attributes = nil, &block)
  679. if attributes.is_a?(Array)
  680. attributes.collect { |attr| create(attr, &block) }
  681. else
  682. object = new(attributes)
  683. yield(object) if block_given?
  684. object.save
  685. object
  686. end
  687. end
  688. # Updates an object (or multiple objects) and saves it to the database, if validations pass.
  689. # The resulting object is returned whether the object was saved successfully to the database or not.
  690. #
  691. # ==== Parameters
  692. #
  693. # * +id+ - This should be the id or an array of ids to be updated.
  694. # * +attributes+ - This should be a hash of attributes to be set on the object, or an array of hashes.
  695. #
  696. # ==== Examples
  697. #
  698. # # Updating one record:
  699. # Person.update(15, :user_name => 'Samuel', :group => 'expert')
  700. #
  701. # # Updating multiple records:
  702. # people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
  703. # Person.update(people.keys, people.values)
  704. def update(id, attributes)
  705. if id.is_a?(Array)
  706. idx = -1
  707. id.collect { |one_id| idx += 1; update(one_id, attributes[idx]) }
  708. else
  709. object = find(id)
  710. object.update_attributes(attributes)
  711. object
  712. end
  713. end
  714. # Deletes the row with a primary key matching the +id+ argument, using a
  715. # SQL +DELETE+ statement, and returns the number of rows deleted. Active
  716. # Record objects are not instantiated, so the object's callbacks are not
  717. # executed, including any <tt>:dependent</tt> association options or
  718. # Observer methods.
  719. #
  720. # You can delete multiple rows at once by passing an Array of <tt>id</tt>s.
  721. #
  722. # Note: Although it is often much faster than the alternative,
  723. # <tt>#destroy</tt>, skipping callbacks might bypass business logic in
  724. # your application that ensures referential integrity or performs other
  725. # essential jobs.
  726. #
  727. # ==== Examples
  728. #
  729. # # Delete a single row
  730. # Todo.delete(1)
  731. #
  732. # # Delete multiple rows
  733. # Todo.delete([2,3,4])
  734. def delete(id)
  735. delete_all([ "#{connection.quote_column_name(primary_key)} IN (?)", id ])
  736. end
  737. # Destroy an object (or multiple objects) that has the given id, the object is instantiated first,
  738. # therefore all callbacks and filters are fired off before the object is deleted. This method is
  739. # less efficient than ActiveRecord#delete but allows cleanup methods and other actions to be run.
  740. #
  741. # This essentially finds the object (or multiple objects) with the given id, creates a new object
  742. # from the attributes, and then calls destroy on it.
  743. #
  744. # ==== Parameters
  745. #
  746. # * +id+ - Can be either an Integer or an Array of Integers.
  747. #
  748. # ==== Examples
  749. #
  750. # # Destroy a single object
  751. # Todo.destroy(1)
  752. #
  753. # # Destroy multiple objects
  754. # todos = [1,2,3]
  755. # Todo.destroy(todos)
  756. def destroy(id)
  757. if id.is_a?(Array)
  758. id.map { |one_id| destroy(one_id) }
  759. else
  760. find(id).destroy
  761. end
  762. end
  763. # Updates all records with details given if they match a set of conditions supplied, limits and order can
  764. # also be supplied. This method constructs a single SQL UPDATE statement and sends it straight to the
  765. # database. It does not instantiate the involved models and it does not trigger Active Record callbacks.
  766. #
  767. # ==== Parameters
  768. #
  769. # * +updates+ - A string of column and value pairs that will be set on any records that match conditions. This creates the SET clause of the generated SQL.
  770. # * +conditions+ - An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro for more info.
  771. # * +options+ - Additional options are <tt>:limit</tt> and <tt>:order</tt>, see the examples for usage.
  772. #
  773. # ==== Examples
  774. #
  775. # # Update all billing objects with the 3 different attributes given
  776. # Billing.update_all( "category = 'authorized', approved = 1, author = 'David'" )
  777. #
  778. # # Update records that match our conditions
  779. # Billing.update_all( "author = 'David'", "title LIKE '%Rails%'" )
  780. #
  781. # # Update records that match our conditions but limit it to 5 ordered by date
  782. # Billing.update_all( "author = 'David'", "title LIKE '%Rails%'",
  783. # :order => 'created_at', :limit => 5 )
  784. def update_all(updates, conditions = nil, options = {})
  785. sql = "UPDATE #{quoted_table_name} SET #{sanitize_sql_for_assignment(updates)} "
  786. scope = scope(:find)
  787. select_sql = ""
  788. add_conditions!(select_sql, conditions, scope)
  789. if options.has_key?(:limit) || (scope && scope[:limit])
  790. # Only take order from scope if limit is also provided by scope, this
  791. # is useful for updating a has_many association with a limit.
  792. add_order!(select_sql, options[:order], scope)
  793. add_limit!(select_sql, options, scope)
  794. sql.concat(connection.limited_update_conditions(select_sql, quoted_table_name, connection.quote_column_name(primary_key)))
  795. else
  796. add_order!(select_sql, options[:order], nil)
  797. sql.concat(select_sql)
  798. end
  799. connection.update(sql, "#{name} Update")
  800. end
  801. # Destroys the records matching +conditions+ by instantiating each
  802. # record and calling its +destroy+ method. Each object's callbacks are
  803. # executed (including <tt>:dependent</tt> association options and
  804. # +before_destroy+/+after_destroy+ Observer methods). Returns the
  805. # collection of objects that were destroyed; each will be frozen, to
  806. # reflect that no changes should be made (since they can't be
  807. # persisted).
  808. #
  809. # Note: Instantiation, callback execution, and deletion of each
  810. # record can be time consuming when you're removing many records at
  811. # once. It generates at least one SQL +DELETE+ query per record (or
  812. # possibly more, to enforce your callbacks). If you want to delete many
  813. # rows quickly, without concern for their associations or callbacks, use
  814. # +delete_all+ instead.
  815. #
  816. # ==== Parameters
  817. #
  818. # * +conditions+ - A string, array, or hash that specifies which records
  819. # to destroy. If omitted, all records are destroyed. See the
  820. # Conditions section in the introduction to ActiveRecord::Base for
  821. # more information.
  822. #
  823. # ==== Examples
  824. #
  825. # Person.destroy_all("last_login < '2004-04-04'")
  826. # Person.destroy_all(:status => "inactive")
  827. def destroy_all(conditions = nil)
  828. find(:all, :conditions => conditions).each { |object| object.destroy }
  829. end
  830. # Deletes the records matching +conditions+ without instantiating the records first, and hence not
  831. # calling the +destroy+ method nor invoking callbacks. This is a single SQL DELETE statement that
  832. # goes straight to the database, much more efficient than +destroy_all+. Be careful with relations
  833. # though, in particular <tt>:dependent</tt> rules defined on associations are not honored. Returns
  834. # the number of rows affected.
  835. #
  836. # ==== Parameters
  837. #
  838. # * +conditions+ - Conditions are specified the same way as with +find+ method.
  839. #
  840. # ==== Example
  841. #
  842. # Post.delete_all("person_id = 5 AND (category = 'Something' OR category = 'Else')")
  843. # Post.delete_all(["person_id = ? AND (category = ? OR category = ?)", 5, 'Something', 'Else'])
  844. #
  845. # Both calls delete the affected posts all at once with a single DELETE statement. If you need to destroy dependent
  846. # associations or call your <tt>before_*</tt> or +after_destroy+ callbacks, use the +destroy_all+ method instead.
  847. def delete_all(conditions = nil)
  848. sql = "DELETE FROM #{quoted_table_name} "
  849. add_conditions!(sql, conditions, scope(:find))
  850. connection.delete(sql, "#{name} Delete all")
  851. end
  852. # Returns the result of an SQL statement that should only include a COUNT(*) in the SELECT part.
  853. # The use of this method should be restricted to complicated SQL queries that can't be executed
  854. # using the ActiveRecord::Calculations class methods. Look into those before using this.
  855. #
  856. # ==== Parameters
  857. #
  858. # * +sql+ - An SQL statement which should return a count query from the database, see the example below.
  859. #
  860. # ==== Examples
  861. #
  862. # Product.count_by_sql "SELECT COUNT(*) FROM sales s, customers c WHERE s.customer_id = c.id"
  863. def count_by_sql(sql)
  864. sql = sanitize_conditions(sql)
  865. connection.select_value(sql, "#{name} Count").to_i
  866. end
  867. # Resets one or more counter caches to their correct value using an SQL
  868. # count query. This is useful when adding new counter caches, or if the
  869. # counter has been corrupted or modified directly by SQL.
  870. #
  871. # ==== Parameters
  872. #
  873. # * +id+ - The id of the object you wish to reset a counter on.
  874. # * +counters+ - One or more counter names to reset
  875. #
  876. # ==== Examples
  877. #
  878. # # For Post with id #1 records reset the comments_count
  879. # Post.reset_counters(1, :comments)
  880. def reset_counters(id, *counters)
  881. object = find(id)
  882. counters.each do |association|
  883. child_class = reflect_on_association(association.to_sym).klass
  884. belongs_name = self.name.demodulize.underscore.to_sym
  885. counter_name = child_class.reflect_on_association(belongs_name).counter_cache_column
  886. value = object.send(association).count
  887. connection.update(<<-CMD, "#{name} UPDATE")
  888. UPDATE #{quoted_table_name}
  889. SET #{connection.quote_column_name(counter_name)} = #{value}
  890. WHERE #{connection.quote_column_name(primary_key)} = #{quote_value(object.id)}
  891. CMD
  892. end
  893. return true
  894. end
  895. # A generic "counter updater" implementation, intended primarily to be
  896. # used by increment_counter and decrement_counter, but which may also
  897. # be useful on its own. It simply does a direct SQL update for the record
  898. # with the given ID, altering the given hash of counters by the amount
  899. # given by the corresponding value:
  900. #
  901. # ==== Parameters
  902. #
  903. # * +id+ - The id of the object you wish to update a counter on or an Array of ids.
  904. # * +counters+ - An Array of Hashes containing the names of the fields
  905. # to update as keys and the amount to update the field by as values.
  906. #
  907. # ==== Examples
  908. #
  909. # # For the Post with id of 5, decrement the comment_count by 1, and
  910. # # increment the action_count by 1
  911. # Post.update_counters 5, :comment_count => -1, :action_count => 1
  912. # # Executes the following SQL:
  913. # # UPDATE posts
  914. # # SET comment_count = comment_count - 1,
  915. # # action_count = action_count + 1
  916. # # WHERE id = 5
  917. #
  918. # # For the Posts with id of 10 and 15, increment the comment_count by 1
  919. # Post.update_counters [10, 15], :comment_count => 1
  920. # # Executes the following SQL:
  921. # # UPDATE posts
  922. # # SET comment_count = comment_count + 1,
  923. # # WHERE id IN (10, 15)
  924. def update_counters(id, counters)
  925. updates = counters.map do |counter_name, value|
  926. operator = value < 0 ? '-' : '+'
  927. quoted_column = connection.quote_column_name(counter_name)
  928. "#{quoted_column} = COALESCE(#{quoted_column}, 0) #{operator} #{value.abs}"
  929. end
  930. update_all(updates.join(', '), primary_key => id )
  931. end
  932. # Increment a number field by one, usually representing a count.
  933. #
  934. # This is used for caching aggregate values, so that they don't need to be computed every time.
  935. # For example, a DiscussionBoard may cache post_count and comment_count otherwise every time the board is
  936. # shown it would have to run an SQL query to find how many posts and comments there are.
  937. #
  938. # ==== Parameters
  939. #
  940. # * +counter_name+ - The name of the field that should be incremented.
  941. # * +id+ - The id of the object that should be incremented.
  942. #
  943. # ==== Examples
  944. #
  945. # # Increment the post_count column for the record with an id of 5
  946. # DiscussionBoard.increment_counter(:post_c

Large files files are truncated, but you can click here to view the full file