Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100755 3169 lines (2863 sloc) 139.721 kb
db045db @dhh Initial
dhh authored
1 require 'yaml'
aabf909 @jeremy Correct reader method generation for primary key attribute: handle case ...
jeremy authored
2 require 'set'
f5d720f @jeremy Opt in to Dependencies
jeremy authored
3 require 'active_support/dependencies'
e8550ee @jeremy Cherry-pick core extensions
jeremy authored
4 require 'active_support/core_ext/class/attribute_accessors'
5 require 'active_support/core_ext/class/delegating_attributes'
6 require 'active_support/core_ext/class/inheritable_attributes'
7 require 'active_support/core_ext/array/extract_options'
8 require 'active_support/core_ext/hash/deep_merge'
9 require 'active_support/core_ext/hash/indifferent_access'
10 require 'active_support/core_ext/hash/slice'
11 require 'active_support/core_ext/string/behavior'
12 require 'active_support/core/time'
db045db @dhh Initial
dhh authored
13
14 module ActiveRecord #:nodoc:
98dc582 @lifo Merge docrails.
lifo authored
15 # Generic Active Record exception class.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
16 class ActiveRecordError < StandardError
db045db @dhh Initial
dhh authored
17 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
18
0432d15 @lifo Merge with docrails.
lifo authored
19 # Raised when the single-table inheritance mechanism fails to locate the subclass
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
20 # (for example due to improper usage of column that +inheritance_column+ points to).
605bc77 @dhh Added a better exception for when a type column is used in a table witho...
dhh authored
21 class SubclassNotFound < ActiveRecordError #:nodoc:
22 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
23
64092de @fxn Improve documentation coverage and markup
fxn authored
24 # Raised when an object assigned to an association has an incorrect type.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
25 #
64092de @fxn Improve documentation coverage and markup
fxn authored
26 # class Ticket < ActiveRecord::Base
27 # has_many :patches
28 # end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
29 #
64092de @fxn Improve documentation coverage and markup
fxn authored
30 # class Patch < ActiveRecord::Base
31 # belongs_to :ticket
32 # end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
33 #
64092de @fxn Improve documentation coverage and markup
fxn authored
34 # # Comments are not patches, this assignment raises AssociationTypeMismatch.
35 # @ticket.patches << Comment.new(:content => "Please attach tests to your patch.")
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
36 class AssociationTypeMismatch < ActiveRecordError
db045db @dhh Initial
dhh authored
37 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
38
39 # Raised when unserialized object's type mismatches one specified for serializable field.
40 class SerializationTypeMismatch < ActiveRecordError
db045db @dhh Initial
dhh authored
41 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
42
98dc582 @lifo Merge docrails.
lifo authored
43 # Raised when adapter not specified on connection (or configuration file <tt>config/database.yml</tt> misses adapter field).
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
44 class AdapterNotSpecified < ActiveRecordError
db045db @dhh Initial
dhh authored
45 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
46
98dc582 @lifo Merge docrails.
lifo authored
47 # Raised when Active Record cannot find database adapter specified in <tt>config/database.yml</tt> or programmatically.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
48 class AdapterNotFound < ActiveRecordError
db045db @dhh Initial
dhh authored
49 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
50
98dc582 @lifo Merge docrails.
lifo authored
51 # Raised when connection to the database could not been established (for example when <tt>connection=</tt> is given a nil object).
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
52 class ConnectionNotEstablished < ActiveRecordError
db045db @dhh Initial
dhh authored
53 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
54
98dc582 @lifo Merge docrails.
lifo authored
55 # Raised when Active Record cannot find record by given id or set of ids.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
56 class RecordNotFound < ActiveRecordError
db045db @dhh Initial
dhh authored
57 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
58
59 # Raised by ActiveRecord::Base.save! and ActiveRecord::Base.create! methods when record cannot be
60 # saved because record is invalid.
61 class RecordNotSaved < ActiveRecordError
4c7555a @dhh Fixed that Base.save should always return false if the save didn't succe...
dhh authored
62 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
63
64 # 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).
65 class StatementInvalid < ActiveRecordError
db045db @dhh Initial
dhh authored
66 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
67
64092de @fxn Improve documentation coverage and markup
fxn authored
68 # Raised when number of bind variables in statement given to <tt>:condition</tt> key (for example, when using +find+ method)
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
69 # does not match number of expected variables.
70 #
64092de @fxn Improve documentation coverage and markup
fxn authored
71 # For example, in
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
72 #
64092de @fxn Improve documentation coverage and markup
fxn authored
73 # Location.find :all, :conditions => ["lat = ? AND lng = ?", 53.7362]
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
74 #
64092de @fxn Improve documentation coverage and markup
fxn authored
75 # two placeholders are given but only one variable to fill them.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
76 class PreparedStatementInvalid < ActiveRecordError
554597d @dhh Added named bind-style variable interpolation #281 [Michael Koziarski]
dhh authored
77 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
78
79 # Raised on attempt to save stale record. Record is stale when it's being saved in another query after
80 # instantiation, for example, when two users edit the same wiki page and one starts editing and saves
81 # the page before the other.
82 #
98dc582 @lifo Merge docrails.
lifo authored
83 # Read more about optimistic locking in ActiveRecord::Locking module RDoc.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
84 class StaleObjectError < ActiveRecordError
fbf9281 @dhh Added automated optimistic locking if the field lock_version is present ...
dhh authored
85 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
86
87 # Raised when association is being configured improperly or
88 # user tries to use offset and limit together with has_many or has_and_belongs_to_many associations.
89 class ConfigurationError < ActiveRecordError
5b9b904 @dhh Added support for limit and offset with eager loading of has_one and bel...
dhh authored
90 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
91
92 # Raised on attempt to update record that is instantiated as read only.
93 class ReadOnlyRecord < ActiveRecordError
64fcb75 @jeremy r3618@sedna: jeremy | 2005-10-14 12:06:03 -0700
jeremy authored
94 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
95
6e75455 @lifo Merge docrails changes
lifo authored
96 # ActiveRecord::Transactions::ClassMethods.transaction uses this exception
97 # to distinguish a deliberate rollback from other exceptional situations.
98 # Normally, raising an exception will cause the +transaction+ method to rollback
99 # the database transaction *and* pass on the exception. But if you raise an
100 # ActiveRecord::Rollback exception, then the database transaction will be rolled back,
101 # without passing on the exception.
102 #
103 # For example, you could do this in your controller to rollback a transaction:
104 #
105 # class BooksController < ActionController::Base
106 # def create
107 # Book.transaction do
108 # book = Book.new(params[:book])
109 # book.save!
110 # if today_is_friday?
111 # # The system must fail on Friday so that our support department
112 # # won't be out of job. We silently rollback this transaction
113 # # without telling the user.
114 # raise ActiveRecord::Rollback, "Call tech support!"
115 # end
116 # end
117 # # ActiveRecord::Rollback is the only exception that won't be passed on
118 # # by ActiveRecord::Base.transaction, so this line will still be reached
119 # # even on Friday.
120 # redirect_to root_url
121 # end
122 # end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
123 class Rollback < ActiveRecordError
5b2e8b1 @technoweenie Fix that ActiveRecord would create attribute methods and override custom...
technoweenie authored
124 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
125
98dc582 @lifo Merge docrails.
lifo authored
126 # Raised when attribute has a name reserved by Active Record (when attribute has name of one of Active Record instance methods).
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
127 class DangerousAttributeError < ActiveRecordError
ebbe4fb @NZKoz Replace the transaction {|transaction|..} semantics with a new Exception...
NZKoz authored
128 end
84a14f2 @jeremy Raise ProtectedAttributeAssignmentError in development and test environm...
jeremy authored
129
dc4eec1 @lifo Merge docrails:
lifo authored
130 # Raised when you've tried to access a column which wasn't loaded by your finder.
131 # Typically this is because <tt>:select</tt> has been specified.
5b801b5 @NZKoz Change the implementation of ActiveRecord's attribute reader and writer ...
NZKoz authored
132 class MissingAttributeError < NoMethodError
133 end
e48b062 @jeremy Sanitize Base#inspect. Closes #8392.
jeremy authored
134
4f68752 @jeremy Revert "Revert "Raise UnknownAttributeError when unknown attributes are ...
jeremy authored
135 # Raised when unknown attributes are supplied via mass assignment.
136 class UnknownAttributeError < NoMethodError
137 end
138
0432d15 @lifo Merge with docrails.
lifo authored
139 # Raised when an error occurred while doing a mass assignment to an attribute through the
dc4eec1 @lifo Merge docrails:
lifo authored
140 # <tt>attributes=</tt> method. The exception has an +attribute+ property that is the name of the
141 # offending attribute.
142 class AttributeAssignmentError < ActiveRecordError
d2fefbe @dhh Added MultiparameterAssignmentErrors and AttributeAssignmentError except...
dhh authored
143 attr_reader :exception, :attribute
144 def initialize(message, exception, attribute)
145 @exception = exception
146 @attribute = attribute
147 @message = message
148 end
149 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
150
dc4eec1 @lifo Merge docrails:
lifo authored
151 # Raised when there are multiple errors while doing a mass assignment through the +attributes+
152 # method. The exception has an +errors+ property that contains an array of AttributeAssignmentError
153 # objects, each corresponding to the error while assigning to an attribute.
154 class MultiparameterAssignmentErrors < ActiveRecordError
d2fefbe @dhh Added MultiparameterAssignmentErrors and AttributeAssignmentError except...
dhh authored
155 attr_reader :errors
156 def initialize(errors)
157 @errors = errors
158 end
159 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
160
2948910 Misc doc fixes (typos/grammar/etc.). Closes #2430.
Marcel Molina authored
161 # Active Record objects don't specify their attributes directly, but rather infer them from the table definition with
db045db @dhh Initial
dhh authored
162 # which they're linked. Adding, removing, and changing attributes and their type is done directly in the database. Any change
163 # is instantly reflected in the Active Record objects. The mapping that binds a given Active Record class to a certain
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
164 # database table will happen automatically in most common cases, but can be overwritten for the uncommon ones.
165 #
db045db @dhh Initial
dhh authored
166 # See the mapping rules in table_name and the full example in link:files/README.html for more insight.
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
167 #
db045db @dhh Initial
dhh authored
168 # == Creation
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
169 #
2948910 Misc doc fixes (typos/grammar/etc.). Closes #2430.
Marcel Molina authored
170 # Active Records accept constructor parameters either in a hash or as a block. The hash method is especially useful when
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobSilv...
Marcel Molina authored
171 # you're receiving the data from somewhere else, like an HTTP request. It works like this:
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
172 #
0591c53 @dhh Made the dynamic finders use the new find API and updated the examples h...
dhh authored
173 # user = User.new(:name => "David", :occupation => "Code Artist")
db045db @dhh Initial
dhh authored
174 # user.name # => "David"
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
175 #
db045db @dhh Initial
dhh authored
176 # You can also use block initialization:
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
177 #
db045db @dhh Initial
dhh authored
178 # user = User.new do |u|
179 # u.name = "David"
180 # u.occupation = "Code Artist"
181 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
182 #
db045db @dhh Initial
dhh authored
183 # And of course you can just create a bare object and specify the attributes after the fact:
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
184 #
db045db @dhh Initial
dhh authored
185 # user = User.new
186 # user.name = "David"
187 # user.occupation = "Code Artist"
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
188 #
db045db @dhh Initial
dhh authored
189 # == Conditions
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
190 #
c5ec16e @dhh Added simple hash conditions to find that'll just convert hash to an AND...
dhh authored
191 # Conditions can either be specified as a string, array, or hash representing the WHERE-part of an SQL statement.
db045db @dhh Initial
dhh authored
192 # The array form is to be used when the condition input is tainted and requires sanitization. The string form can
c5ec16e @dhh Added simple hash conditions to find that'll just convert hash to an AND...
dhh authored
193 # be used for statements that don't involve tainted data. The hash form works much like the array form, except
2876707 @jeremy Pass a range in :conditions to use the SQL BETWEEN operator. Closes #697...
jeremy authored
194 # only equality and range is possible. Examples:
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
195 #
48052d7 @jeremy to_xml fixes, features, and speedup. Closes #4989.
jeremy authored
196 # class User < ActiveRecord::Base
db045db @dhh Initial
dhh authored
197 # def self.authenticate_unsafely(user_name, password)
3dfa56c @dhh Updated all references to the old find_first and find_all to use the new...
dhh authored
198 # find(:first, :conditions => "user_name = '#{user_name}' AND password = '#{password}'")
db045db @dhh Initial
dhh authored
199 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
200 #
db045db @dhh Initial
dhh authored
201 # def self.authenticate_safely(user_name, password)
3dfa56c @dhh Updated all references to the old find_first and find_all to use the new...
dhh authored
202 # find(:first, :conditions => [ "user_name = ? AND password = ?", user_name, password ])
db045db @dhh Initial
dhh authored
203 # end
c5ec16e @dhh Added simple hash conditions to find that'll just convert hash to an AND...
dhh authored
204 #
205 # def self.authenticate_safely_simply(user_name, password)
206 # find(:first, :conditions => { :user_name => user_name, :password => password })
207 # end
db045db @dhh Initial
dhh authored
208 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
209 #
2575b3b @dhh Added extra words of caution for guarding against SQL-injection attacks
dhh authored
210 # The <tt>authenticate_unsafely</tt> method inserts the parameters directly into the query and is thus susceptible to SQL-injection
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobSilv...
Marcel Molina authored
211 # attacks if the <tt>user_name</tt> and +password+ parameters come directly from an HTTP request. The <tt>authenticate_safely</tt> and
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
212 # <tt>authenticate_safely_simply</tt> both will sanitize the <tt>user_name</tt> and +password+ before inserting them in the query,
c5ec16e @dhh Added simple hash conditions to find that'll just convert hash to an AND...
dhh authored
213 # which will ensure that an attacker can't escape the query and fake the login (or worse).
2575b3b @dhh Added extra words of caution for guarding against SQL-injection attacks
dhh authored
214 #
5cd38ca @dhh Added documentation about named bind variables
dhh authored
215 # When using multiple parameters in the conditions, it can easily become hard to read exactly what the fourth or fifth
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
216 # question mark is supposed to represent. In those cases, you can resort to named bind variables instead. That's done by replacing
5cd38ca @dhh Added documentation about named bind variables
dhh authored
217 # the question marks with symbols and supplying a hash with values for the matching symbol keys:
218 #
a7e6e00 Documentation for find incorrectly omits the :conditions option from var...
Marcel Molina authored
219 # Company.find(:first, :conditions => [
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
220 # "id = :id AND name = :name AND division = :division AND created_at > :accounting_date",
5cd38ca @dhh Added documentation about named bind variables
dhh authored
221 # { :id => 3, :name => "37signals", :division => "First", :accounting_date => '2005-01-01' }
222 # ])
223 #
c5ec16e @dhh Added simple hash conditions to find that'll just convert hash to an AND...
dhh authored
224 # Similarly, a simple hash without a statement will generate conditions based on equality with the SQL AND
225 # operator. For instance:
226 #
227 # Student.find(:all, :conditions => { :first_name => "Harvey", :status => 1 })
228 # Student.find(:all, :conditions => params[:student])
229 #
2876707 @jeremy Pass a range in :conditions to use the SQL BETWEEN operator. Closes #697...
jeremy authored
230 # A range may be used in the hash to use the SQL BETWEEN operator:
231 #
232 # Student.find(:all, :conditions => { :grade => 9..12 })
c5ec16e @dhh Added simple hash conditions to find that'll just convert hash to an AND...
dhh authored
233 #
aa4af60 @lifo Improve documentation.
lifo authored
234 # An array may be used in the hash to use the SQL IN operator:
235 #
236 # Student.find(:all, :conditions => { :grade => [9,11,12] })
237 #
db045db @dhh Initial
dhh authored
238 # == Overwriting default accessors
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
239 #
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobSilv...
Marcel Molina authored
240 # All column values are automatically available through basic accessors on the Active Record object, but sometimes you
241 # want to specialize this behavior. This can be done by overwriting the default accessors (using the same
98dc582 @lifo Merge docrails.
lifo authored
242 # name as the attribute) and calling <tt>read_attribute(attr_name)</tt> and <tt>write_attribute(attr_name, value)</tt> to actually change things.
db045db @dhh Initial
dhh authored
243 # Example:
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
244 #
db045db @dhh Initial
dhh authored
245 # class Song < ActiveRecord::Base
246 # # Uses an integer of seconds to hold the length of the song
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
247 #
db045db @dhh Initial
dhh authored
248 # def length=(minutes)
64092de @fxn Improve documentation coverage and markup
fxn authored
249 # write_attribute(:length, minutes.to_i * 60)
db045db @dhh Initial
dhh authored
250 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
251 #
db045db @dhh Initial
dhh authored
252 # def length
0591c53 @dhh Made the dynamic finders use the new find API and updated the examples h...
dhh authored
253 # read_attribute(:length) / 60
db045db @dhh Initial
dhh authored
254 # end
255 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
256 #
98dc582 @lifo Merge docrails.
lifo authored
257 # You can alternatively use <tt>self[:attribute]=(value)</tt> and <tt>self[:attribute]</tt> instead of <tt>write_attribute(:attribute, value)</tt> and
258 # <tt>read_attribute(:attribute)</tt> as a shorter form.
0591c53 @dhh Made the dynamic finders use the new find API and updated the examples h...
dhh authored
259 #
e4d845e Document automatically generated predicate methods for attributes. Close...
Marcel Molina authored
260 # == Attribute query methods
261 #
262 # In addition to the basic accessors, query methods are also automatically available on the Active Record object.
263 # Query methods allow you to test whether an attribute value is present.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
264 #
e4d845e Document automatically generated predicate methods for attributes. Close...
Marcel Molina authored
265 # For example, an Active Record User with the <tt>name</tt> attribute has a <tt>name?</tt> method that you can call
266 # to determine whether the user has a name:
267 #
268 # user = User.new(:name => "David")
269 # user.name? # => true
270 #
271 # anonymous = User.new(:name => "")
272 # anonymous.name? # => false
273 #
2948910 Misc doc fixes (typos/grammar/etc.). Closes #2430.
Marcel Molina authored
274 # == Accessing attributes before they have been typecasted
4eab375 @dhh Finished polishing API docs
dhh authored
275 #
2948910 Misc doc fixes (typos/grammar/etc.). Closes #2430.
Marcel Molina authored
276 # Sometimes you want to be able to read the raw attribute data without having the column-determined typecast run its course first.
dc4eec1 @lifo Merge docrails:
lifo authored
277 # That can be done by using the <tt><attribute>_before_type_cast</tt> accessors that all attributes have. For example, if your Account model
98dc582 @lifo Merge docrails.
lifo authored
278 # has a <tt>balance</tt> attribute, you can call <tt>account.balance_before_type_cast</tt> or <tt>account.id_before_type_cast</tt>.
4eab375 @dhh Finished polishing API docs
dhh authored
279 #
280 # This is especially useful in validation situations where the user might supply a string for an integer field and you want to display
2948910 Misc doc fixes (typos/grammar/etc.). Closes #2430.
Marcel Molina authored
281 # the original string back in an error message. Accessing the attribute normally would typecast the string to 0, which isn't what you
4eab375 @dhh Finished polishing API docs
dhh authored
282 # want.
283 #
ac8fd7d @dhh Added dynamic attribute-based finders as a cleaner way of getting object...
dhh authored
284 # == Dynamic attribute-based finders
285 #
a5a82d9 @dhh Added extension capabilities to has_many and has_and_belongs_to_many pro...
dhh authored
286 # Dynamic attribute-based finders are a cleaner way of getting (and/or creating) objects by simple queries without turning to SQL. They work by
6dc9173 @dhh Missing doc updates
dhh authored
287 # 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>,
98dc582 @lifo Merge docrails.
lifo authored
288 # <tt>Person.find_all_by_last_name</tt>, and <tt>Payment.find_by_transaction_id</tt>. So instead of writing
a7e6e00 Documentation for find incorrectly omits the :conditions option from var...
Marcel Molina authored
289 # <tt>Person.find(:first, :conditions => ["user_name = ?", user_name])</tt>, you just do <tt>Person.find_by_user_name(user_name)</tt>.
290 # 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>.
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
291 #
ac8fd7d @dhh Added dynamic attribute-based finders as a cleaner way of getting object...
dhh authored
292 # It's also possible to use multiple attributes in the same find by separating them with "_and_", so you get finders like
293 # <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
a7e6e00 Documentation for find incorrectly omits the :conditions option from var...
Marcel Molina authored
294 # <tt>Person.find(:first, :conditions => ["user_name = ? AND password = ?", user_name, password])</tt>, you just do
ac8fd7d @dhh Added dynamic attribute-based finders as a cleaner way of getting object...
dhh authored
295 # <tt>Person.find_by_user_name_and_password(user_name, password)</tt>.
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
296 #
98dc582 @lifo Merge docrails.
lifo authored
297 # 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>
298 # is actually <tt>Payment.find_all_by_amount(amount, options)</tt>. And the full interface to <tt>Person.find_by_user_name</tt> is
64092de @fxn Improve documentation coverage and markup
fxn authored
299 # 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>.
567392b @miloops Added find_last_by dynamic finder [status:committed #762]
miloops authored
300 # Also you may call <tt>Payment.find_last_by_amount(amount, options)</tt> returning the last record matching that amount and options.
959f362 @dhh Added find_all style to the new dynamic finders
dhh authored
301 #
a5a82d9 @dhh Added extension capabilities to has_many and has_and_belongs_to_many pro...
dhh authored
302 # The same dynamic finder style can be used to create the object if it doesn't already exist. This dynamic finder is called with
5c47ceb @NZKoz Typo fix in documentation from [9090] References #11422
NZKoz authored
303 # <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:
a5a82d9 @dhh Added extension capabilities to has_many and has_and_belongs_to_many pro...
dhh authored
304 #
305 # # No 'Summer' tag exists
306 # Tag.find_or_create_by_name("Summer") # equal to Tag.create(:name => "Summer")
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
307 #
a5a82d9 @dhh Added extension capabilities to has_many and has_and_belongs_to_many pro...
dhh authored
308 # # Now the 'Summer' tag does exist
309 # Tag.find_or_create_by_name("Summer") # equal to Tag.find_by_name("Summer")
310 #
c10b225 @dhh Fixed that ActiveRecord#Base.find_or_create/initialize would not honor a...
dhh authored
311 # # Now 'Bob' exist and is an 'admin'
312 # User.find_or_create_by_name('Bob', :age => 40) { |u| u.admin = true }
313 #
0432d15 @lifo Merge with docrails.
lifo authored
314 # 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:
d19e464 @sstephenson Added find_or_initialize_by_X which works like find_or_create_by_X but d...
sstephenson authored
315 #
316 # # No 'Winter' tag exists
317 # winter = Tag.find_or_initialize_by_name("Winter")
85fbb22 @dhh Backed out of new_record? to new? transformation as it would screw up ex...
dhh authored
318 # winter.new_record? # true
d19e464 @sstephenson Added find_or_initialize_by_X which works like find_or_create_by_X but d...
sstephenson authored
319 #
14cc8d2 @jeremy find_or_create_by_* takes a hash so you can create with more attributes ...
jeremy authored
320 # To find by a subset of the attributes to be used for instantiating a new object, pass a hash instead of
321 # a list of parameters. For example:
322 #
323 # Tag.find_or_create_by_name(:name => "rails", :creator => current_user)
324 #
325 # That will either find an existing tag named "rails", or create a new one while setting the user that created it.
326 #
098fa94 @dhh Fixed documentation snafus #575, #576, #577, #585
dhh authored
327 # == Saving arrays, hashes, and other non-mappable objects in text columns
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
328 #
329 # 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+.
2948910 Misc doc fixes (typos/grammar/etc.). Closes #2430.
Marcel Molina authored
330 # This makes it possible to store arrays, hashes, and other non-mappable objects without doing any additional work. Example:
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
331 #
db045db @dhh Initial
dhh authored
332 # class User < ActiveRecord::Base
333 # serialize :preferences
334 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
335 #
ca2eb16 Fix syntax error in documentation. Closes #4679. [mislav@nippur.irb.hr]
Marcel Molina authored
336 # user = User.create(:preferences => { "background" => "black", "display" => large })
db045db @dhh Initial
dhh authored
337 # User.find(user.id).preferences # => { "background" => "black", "display" => large }
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
338 #
2948910 Misc doc fixes (typos/grammar/etc.). Closes #2430.
Marcel Molina authored
339 # You can also specify a class option as the second parameter that'll raise an exception if a serialized object is retrieved as a
39e1ac6 @lifo Merge docrails
lifo authored
340 # descendant of a class not in the hierarchy. Example:
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
341 #
db045db @dhh Initial
dhh authored
342 # class User < ActiveRecord::Base
66f44e6 @dhh Updated documentation for serialize
dhh authored
343 # serialize :preferences, Hash
db045db @dhh Initial
dhh authored
344 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
345 #
0591c53 @dhh Made the dynamic finders use the new find API and updated the examples h...
dhh authored
346 # user = User.create(:preferences => %w( one two three ))
db045db @dhh Initial
dhh authored
347 # User.find(user.id).preferences # raises SerializationTypeMismatch
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
348 #
db045db @dhh Initial
dhh authored
349 # == Single table inheritance
350 #
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobSilv...
Marcel Molina authored
351 # Active Record allows inheritance by storing the name of the class in a column that by default is named "type" (can be changed
db045db @dhh Initial
dhh authored
352 # by overwriting <tt>Base.inheritance_column</tt>). This means that an inheritance looking like this:
353 #
354 # class Company < ActiveRecord::Base; end
355 # class Firm < Company; end
356 # class Client < Company; end
357 # class PriorityClient < Client; end
358 #
98dc582 @lifo Merge docrails.
lifo authored
359 # When you do <tt>Firm.create(:name => "37signals")</tt>, this record will be saved in the companies table with type = "Firm". You can then
360 # fetch this row again using <tt>Company.find(:first, "name = '37signals'")</tt> and it will return a Firm object.
db045db @dhh Initial
dhh authored
361 #
f033833 @dhh Improving documentation...
dhh authored
362 # 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
363 # like normal subclasses with no special magic for differentiating between them or reloading the right type with find.
364 #
db045db @dhh Initial
dhh authored
365 # Note, all the attributes for all the cases are kept in the same table. Read more:
366 # http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
367 #
db045db @dhh Initial
dhh authored
368 # == Connection to multiple databases in different models
369 #
370 # Connections are usually created through ActiveRecord::Base.establish_connection and retrieved by ActiveRecord::Base.connection.
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
371 # All classes inheriting from ActiveRecord::Base will use this connection. But you can also set a class-specific connection.
98dc582 @lifo Merge docrails.
lifo authored
372 # For example, if Course is an ActiveRecord::Base, but resides in a different database, you can just say <tt>Course.establish_connection</tt>
373 # and Course and all of its subclasses will use this connection instead.
db045db @dhh Initial
dhh authored
374 #
375 # This feature is implemented by keeping a connection pool in ActiveRecord::Base that is a Hash indexed by the class. If a connection is
376 # requested, the retrieve_connection method will go up the class-hierarchy until a connection is found in the connection pool.
377 #
378 # == Exceptions
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
379 #
dc4eec1 @lifo Merge docrails:
lifo authored
380 # * ActiveRecordError - Generic error class and superclass of all other errors raised by Active Record.
381 # * AdapterNotSpecified - The configuration hash used in <tt>establish_connection</tt> didn't include an
db045db @dhh Initial
dhh authored
382 # <tt>:adapter</tt> key.
dc4eec1 @lifo Merge docrails:
lifo authored
383 # * AdapterNotFound - The <tt>:adapter</tt> key used in <tt>establish_connection</tt> specified a non-existent adapter
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
384 # (or a bad spelling of an existing one).
dc4eec1 @lifo Merge docrails:
lifo authored
385 # * AssociationTypeMismatch - The object assigned to the association wasn't of the type specified in the association definition.
386 # * SerializationTypeMismatch - The serialized object wasn't of the class specified as the second parameter.
387 # * ConnectionNotEstablished+ - No connection has been established. Use <tt>establish_connection</tt> before querying.
388 # * RecordNotFound - No record responded to the +find+ method. Either the row with the given ID doesn't exist
389 # or the row didn't meet the additional restrictions. Some +find+ calls do not raise this exception to signal
390 # nothing was found, please check its documentation for further details.
391 # * StatementInvalid - The database server rejected the SQL statement. The precise error is added in the message.
392 # * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the
393 # <tt>attributes=</tt> method. The +errors+ property of this exception contains an array of AttributeAssignmentError
d2fefbe @dhh Added MultiparameterAssignmentErrors and AttributeAssignmentError except...
dhh authored
394 # objects that should be inspected to determine which attributes triggered the errors.
dc4eec1 @lifo Merge docrails:
lifo authored
395 # * AttributeAssignmentError - An error occurred while doing a mass assignment through the <tt>attributes=</tt> method.
d2fefbe @dhh Added MultiparameterAssignmentErrors and AttributeAssignmentError except...
dhh authored
396 # You can inspect the +attribute+ property of the exception object to determine which attribute triggered the error.
5707027 @dhh Added better exception error when unknown column types are used with mig...
dhh authored
397 #
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
398 # *Note*: The attributes listed are class-level attributes (accessible from both the class and instance level).
dc4eec1 @lifo Merge docrails:
lifo authored
399 # So it's possible to assign a logger to the class through <tt>Base.logger=</tt> which will then be used by all
db045db @dhh Initial
dhh authored
400 # instances in the current object space.
401 class Base
dbbae5e @lifo Merge with docrails
lifo authored
402 ##
403 # :singleton-method:
db045db @dhh Initial
dhh authored
404 # Accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then passed
405 # on to any new database connections made and which can be retrieved on both a class and instance level by calling +logger+.
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7401...
technoweenie authored
406 cattr_accessor :logger, :instance_writer => false
e694114 @jeremy Deprecation: removed Reloadable.
jeremy authored
407
db045db @dhh Initial
dhh authored
408 def self.inherited(child) #:nodoc:
409 @@subclasses[self] ||= []
410 @@subclasses[self] << child
411 super
412 end
e694114 @jeremy Deprecation: removed Reloadable.
jeremy authored
413
fed7d33 @dhh Fixed documentation
dhh authored
414 def self.reset_subclasses #:nodoc:
bfbf6bb @jamis Allow ARStore::Session to indicate that it should not be reloaded in dev...
jamis authored
415 nonreloadables = []
e7f61ea @jamis squash the memleak in dev mode finally (fingers crossed, here)
jamis authored
416 subclasses.each do |klass|
c08547d @josh Namespace Inflector, Dependencies, OrderedOptions, and TimeZone under Ac...
josh authored
417 unless ActiveSupport::Dependencies.autoloaded? klass
bfbf6bb @jamis Allow ARStore::Session to indicate that it should not be reloaded in dev...
jamis authored
418 nonreloadables << klass
419 next
420 end
e7f61ea @jamis squash the memleak in dev mode finally (fingers crossed, here)
jamis authored
421 klass.instance_variables.each { |var| klass.send(:remove_instance_variable, var) }
422 klass.instance_methods(false).each { |m| klass.send :undef_method, m }
423 end
bfbf6bb @jamis Allow ARStore::Session to indicate that it should not be reloaded in dev...
jamis authored
424 @@subclasses = {}
425 nonreloadables.each { |klass| (@@subclasses[klass.superclass] ||= []) << klass }
3c0129a @dhh Fixed memory leak with Active Record classes when Dependencies.mechanism...
dhh authored
426 end
427
db045db @dhh Initial
dhh authored
428 @@subclasses = {}
c3aa2bc @Manfred Ensure nested with_scope merges conditions inside out [#2193 state:resol...
Manfred authored
429
dbbae5e @lifo Merge with docrails
lifo authored
430 ##
431 # :singleton-method:
a293278 @lifo Merge docrails
lifo authored
432 # Contains the database configuration - as is typically stored in config/database.yml -
433 # as a Hash.
434 #
435 # For example, the following database.yml...
436 #
437 # development:
438 # adapter: sqlite3
439 # database: db/development.sqlite3
440 #
441 # production:
442 # adapter: sqlite3
443 # database: db/production.sqlite3
444 #
445 # ...would result in ActiveRecord::Base.configurations to look like this:
446 #
447 # {
448 # 'development' => {
449 # 'adapter' => 'sqlite3',
450 # 'database' => 'db/development.sqlite3'
451 # },
452 # 'production' => {
453 # 'adapter' => 'sqlite3',
454 # 'database' => 'db/production.sqlite3'
455 # }
456 # }
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7401...
technoweenie authored
457 cattr_accessor :configurations, :instance_writer => false
c4a3634 @jeremy Corrected @@configurations typo. #1410 [david@ruppconsulting.com]
jeremy authored
458 @@configurations = {}
459
dbbae5e @lifo Merge with docrails
lifo authored
460 ##
461 # :singleton-method:
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
462 # Accessor for the prefix type that will be prepended to every primary key column name. The options are :table_name and
db045db @dhh Initial
dhh authored
463 # :table_name_with_underscore. If the first is specified, the Product class will look for "productid" instead of "id" as
464 # the primary column. If the latter is specified, the Product class will look for "product_id" instead of "id". Remember
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
465 # that this is a global setting for all Active Records.
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7401...
technoweenie authored
466 cattr_accessor :primary_key_prefix_type, :instance_writer => false
db045db @dhh Initial
dhh authored
467 @@primary_key_prefix_type = nil
468
dbbae5e @lifo Merge with docrails
lifo authored
469 ##
470 # :singleton-method:
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
471 # Accessor for the name of the prefix string to prepend to every table name. So if set to "basecamp_", all
098fa94 @dhh Fixed documentation snafus #575, #576, #577, #585
dhh authored
472 # table names will be named like "basecamp_projects", "basecamp_people", etc. This is a convenient way of creating a namespace
db045db @dhh Initial
dhh authored
473 # for tables in a shared database. By default, the prefix is the empty string.
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7401...
technoweenie authored
474 cattr_accessor :table_name_prefix, :instance_writer => false
db045db @dhh Initial
dhh authored
475 @@table_name_prefix = ""
476
dbbae5e @lifo Merge with docrails
lifo authored
477 ##
478 # :singleton-method:
db045db @dhh Initial
dhh authored
479 # Works like +table_name_prefix+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp",
480 # "people_basecamp"). By default, the suffix is the empty string.
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7401...
technoweenie authored
481 cattr_accessor :table_name_suffix, :instance_writer => false
db045db @dhh Initial
dhh authored
482 @@table_name_suffix = ""
483
dbbae5e @lifo Merge with docrails
lifo authored
484 ##
485 # :singleton-method:
84a14f2 @jeremy Raise ProtectedAttributeAssignmentError in development and test environm...
jeremy authored
486 # Indicates whether table names should be the pluralized versions of the corresponding class names.
98dc582 @lifo Merge docrails.
lifo authored
487 # If true, the default table name for a Product class will be +products+. If false, it would just be +product+.
db045db @dhh Initial
dhh authored
488 # See table_name for the full rules on table/class naming. This is true, by default.
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7401...
technoweenie authored
489 cattr_accessor :pluralize_table_names, :instance_writer => false
db045db @dhh Initial
dhh authored
490 @@pluralize_table_names = true
491
dbbae5e @lifo Merge with docrails
lifo authored
492 ##
493 # :singleton-method:
84a14f2 @jeremy Raise ProtectedAttributeAssignmentError in development and test environm...
jeremy authored
494 # Determines whether to use ANSI codes to colorize the logging statements committed by the connection adapter. These colors
2948910 Misc doc fixes (typos/grammar/etc.). Closes #2430.
Marcel Molina authored
495 # make it much easier to overview things during debugging (when used through a reader like +tail+ and on a black background), but
911614d @dhh Added ActiveRecord::Base.colorize_logging to control whether to use colo...
dhh authored
496 # may complicate matters if you use software like syslog. This is true, by default.
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7401...
technoweenie authored
497 cattr_accessor :colorize_logging, :instance_writer => false
911614d @dhh Added ActiveRecord::Base.colorize_logging to control whether to use colo...
dhh authored
498 @@colorize_logging = true
499
dbbae5e @lifo Merge with docrails
lifo authored
500 ##
501 # :singleton-method:
60de8c1 @dhh Added Base.default_timezone accessor that determines whether to use Time...
dhh authored
502 # Determines whether to use Time.local (using :local) or Time.utc (using :utc) when pulling dates and times from the database.
503 # This is set to :local by default.
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7401...
technoweenie authored
504 cattr_accessor :default_timezone, :instance_writer => false
60de8c1 @dhh Added Base.default_timezone accessor that determines whether to use Time...
dhh authored
505 @@default_timezone = :local
d8641ca @jeremy CHANGED DEFAULT: set ActiveRecord::Base.allow_concurrency to false. Mos...
jeremy authored
506
dbbae5e @lifo Merge with docrails
lifo authored
507 ##
508 # :singleton-method:
24c3599 @sstephenson Support using different database adapters for development and test with ...
sstephenson authored
509 # Specifies the format to use when dumping the database schema with Rails'
510 # Rakefile. If :sql, the schema is dumped as (potentially database-
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
511 # specific) SQL statements. If :ruby, the schema is dumped as an
24c3599 @sstephenson Support using different database adapters for development and test with ...
sstephenson authored
512 # ActiveRecord::Schema file which can be loaded into any database that
513 # supports migrations. Use :ruby if you want to have different database
514 # adapters for, e.g., your development and test environments.
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7401...
technoweenie authored
515 cattr_accessor :schema_format , :instance_writer => false
660952e @dhh CHANGED DEFAULT: ActiveRecord::Base.schema_format is now :ruby by defaul...
dhh authored
516 @@schema_format = :ruby
3b0e1d9 @josh Prefer string core_ext inflector methods over directly accessing Inflect...
josh authored
517
dbbae5e @lifo Merge with docrails
lifo authored
518 ##
519 # :singleton-method:
bbab639 @nikz Set config.active_record.timestamped_migrations = false to have migratio...
nikz authored
520 # Specify whether or not to use timestamps for migration numbers
521 cattr_accessor :timestamped_migrations , :instance_writer => false
522 @@timestamped_migrations = true
523
bca8751 @divoxx Add ActiveRecord option to store the full class name on STI's type colum...
divoxx authored
524 # Determine whether to store the full constant name including namespace when using STI
525 superclass_delegating_accessor :store_full_sti_class
526 self.store_full_sti_class = false
3b0e1d9 @josh Prefer string core_ext inflector methods over directly accessing Inflect...
josh authored
527
2530d0e @lifo Added default_scope to Base [#1381 state:committed] (Paweł Kondzior)
lifo authored
528 # Stores the default scope for the class
529 class_inheritable_accessor :default_scoping, :instance_writer => false
530 self.default_scoping = []
531
db045db @dhh Initial
dhh authored
532 class << self # Class methods
d5a4d5a @dhh Added ActiveRecord::Base.find(:last) (closes #11338) [miloops]
dhh authored
533 # Find operates with four different retrieval approaches:
7669011 @dhh Fixes for postgresql testing #1129, #1130, #1131
dhh authored
534 #
98dc582 @lifo Merge docrails.
lifo authored
535 # * 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]).
7669011 @dhh Fixes for postgresql testing #1129, #1130, #1131
dhh authored
536 # If no record can be found for all of the listed ids, then RecordNotFound will be raised.
98dc582 @lifo Merge docrails.
lifo authored
537 # * Find first - This will return the first record matched by the options used. These options can either be specific
538 # conditions or merely an order. If no record can be matched, +nil+ is returned. Use
539 # <tt>Model.find(:first, *args)</tt> or its shortcut <tt>Model.first(*args)</tt>.
540 # * Find last - This will return the last record matched by the options used. These options can either be specific
541 # conditions or merely an order. If no record can be matched, +nil+ is returned. Use
542 # <tt>Model.find(:last, *args)</tt> or its shortcut <tt>Model.last(*args)</tt>.
543 # * Find all - This will return all the records matched by the options used.
544 # If no records are found, an empty array is returned. Use
545 # <tt>Model.find(:all, *args)</tt> or its shortcut <tt>Model.all(*args)</tt>.
546 #
547 # All approaches accept an options hash as their last parameter.
548 #
a293278 @lifo Merge docrails
lifo authored
549 # ==== Parameters
98dc582 @lifo Merge docrails.
lifo authored
550 #
9cb5400 @lifo Merge docrails
lifo authored
551 # * <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.
98dc582 @lifo Merge docrails.
lifo authored
552 # * <tt>:order</tt> - An SQL fragment like "created_at DESC, name".
553 # * <tt>:group</tt> - An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause.
97403ad @miloops Add :having option to find, to use in combination with grouped finds. Al...
miloops authored
554 # * <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.
98dc582 @lifo Merge docrails.
lifo authored
555 # * <tt>:limit</tt> - An integer determining the limit on the number of rows that should be returned.
556 # * <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.
39e1ac6 @lifo Merge docrails
lifo authored
557 # * <tt>:joins</tt> - Either an SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id" (rarely needed),
558 # 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),
559 # or an array containing a mixture of both strings and named associations.
9661395 Remove references to nonexistent :joins documentation. Closes #10498 [tp...
Marcel Molina authored
560 # 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.
64092de @fxn Improve documentation coverage and markup
fxn authored
561 # Pass <tt>:readonly => false</tt> to override.
98dc582 @lifo Merge docrails.
lifo authored
562 # * <tt>:include</tt> - Names associations that should be loaded alongside. The symbols named refer
515886a @dhh Added documentation for new Base.find API and eager association loading
dhh authored
563 # to already defined associations. See eager loading under Associations.
98dc582 @lifo Merge docrails.
lifo authored
564 # * <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
6ef3546 @lifo Merge docrails
lifo authored
565 # include the joined columns. Takes a string with the SELECT SQL fragment (e.g. "id, name").
98dc582 @lifo Merge docrails.
lifo authored
566 # * <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
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
567 # of a database view).
98dc582 @lifo Merge docrails.
lifo authored
568 # * <tt>:readonly</tt> - Mark the returned records read-only so they cannot be saved or updated.
569 # * <tt>:lock</tt> - An SQL fragment like "FOR UPDATE" or "LOCK IN SHARE MODE".
64092de @fxn Improve documentation coverage and markup
fxn authored
570 # <tt>:lock => true</tt> gives connection's default exclusive lock, usually "FOR UPDATE".
7669011 @dhh Fixes for postgresql testing #1129, #1130, #1131
dhh authored
571 #
98dc582 @lifo Merge docrails.
lifo authored
572 # ==== Examples
573 #
574 # # find by id
db045db @dhh Initial
dhh authored
575 # Person.find(1) # returns the object for ID = 1
576 # Person.find(1, 2, 6) # returns an array for objects with IDs in (1, 2, 6)
577 # Person.find([7, 17]) # returns an array for objects with IDs in (7, 17)
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobSilv...
Marcel Molina authored
578 # Person.find([1]) # returns an array for the object with ID = 1
515886a @dhh Added documentation for new Base.find API and eager association loading
dhh authored
579 # Person.find(1, :conditions => "administrator = 1", :order => "created_on DESC")
580 #
1e9e198 @jeremy Note that find results may not be in the same order as the id arguments....
jeremy authored
581 # Note that returned records may not be in the same order as the ids you
64092de @fxn Improve documentation coverage and markup
fxn authored
582 # provide since database rows are unordered. Give an explicit <tt>:order</tt>
1e9e198 @jeremy Note that find results may not be in the same order as the id arguments....
jeremy authored
583 # to ensure the results are sorted.
584 #
98dc582 @lifo Merge docrails.
lifo authored
585 # ==== Examples
586 #
587 # # find first
7d01005 @dhh Fixed documentation and prepared for release of 0.12
dhh authored
588 # Person.find(:first) # returns the first object fetched by SELECT * FROM people
515886a @dhh Added documentation for new Base.find API and eager association loading
dhh authored
589 # Person.find(:first, :conditions => [ "user_name = ?", user_name])
9cb5400 @lifo Merge docrails
lifo authored
590 # Person.find(:first, :conditions => [ "user_name = :u", { :u => user_name }])
515886a @dhh Added documentation for new Base.find API and eager association loading
dhh authored
591 # Person.find(:first, :order => "created_on DESC", :offset => 5)
592 #
98dc582 @lifo Merge docrails.
lifo authored
593 # # find last
d5a4d5a @dhh Added ActiveRecord::Base.find(:last) (closes #11338) [miloops]
dhh authored
594 # Person.find(:last) # returns the last object fetched by SELECT * FROM people
595 # Person.find(:last, :conditions => [ "user_name = ?", user_name])
596 # Person.find(:last, :order => "created_on DESC", :offset => 5)
597 #
98dc582 @lifo Merge docrails.
lifo authored
598 # # find all
7d01005 @dhh Fixed documentation and prepared for release of 0.12
dhh authored
599 # Person.find(:all) # returns an array of objects for all the rows fetched by SELECT * FROM people
515886a @dhh Added documentation for new Base.find API and eager association loading
dhh authored
600 # Person.find(:all, :conditions => [ "category IN (?)", categories], :limit => 50)
aa4af60 @lifo Improve documentation.
lifo authored
601 # Person.find(:all, :conditions => { :friends => ["Bob", "Steve", "Fred"] }
515886a @dhh Added documentation for new Base.find API and eager association loading
dhh authored
602 # Person.find(:all, :offset => 10, :limit => 10)
603 # Person.find(:all, :include => [ :account, :friends ])
3309268 @jeremy Add :group option, correspond to GROUP BY, to the find method and to the...
jeremy authored
604 # Person.find(:all, :group => "category")
15aa6e0 @jeremy r4644@asus: jeremy | 2006-06-16 14:57:03 -0700
jeremy authored
605 #
98dc582 @lifo Merge docrails.
lifo authored
606 # Example for find with a lock: Imagine two concurrent transactions:
607 # each will read <tt>person.visits == 2</tt>, add 1 to it, and save, resulting
608 # in two saves of <tt>person.visits = 3</tt>. By locking the row, the second
15aa6e0 @jeremy r4644@asus: jeremy | 2006-06-16 14:57:03 -0700
jeremy authored
609 # transaction has to wait until the first is finished; we get the
98dc582 @lifo Merge docrails.
lifo authored
610 # expected <tt>person.visits == 4</tt>.
611 #
15aa6e0 @jeremy r4644@asus: jeremy | 2006-06-16 14:57:03 -0700
jeremy authored
612 # Person.transaction do
613 # person = Person.find(1, :lock => true)
614 # person.visits += 1
615 # person.save!
616 # end
6bd672e @dhh Added that Base#find takes an optional options hash, including :conditio...
dhh authored
617 def find(*args)
edd68a5 @dhh Refactored in use of extract_options! (closes #9079) [josh]
dhh authored
618 options = args.extract_options!
c9c1852 @dhh Making ActiveRecord faster [skaes]
dhh authored
619 validate_find_options(options)
620 set_readonly_option!(options)
64fcb75 @jeremy r3618@sedna: jeremy | 2005-10-14 12:06:03 -0700
jeremy authored
621
abc895b @dhh Added new Base.find API and deprecated find_all, find_first. Added preli...
dhh authored
622 case args.first
c9c1852 @dhh Making ActiveRecord faster [skaes]
dhh authored
623 when :first then find_initial(options)
d5a4d5a @dhh Added ActiveRecord::Base.find(:last) (closes #11338) [miloops]
dhh authored
624 when :last then find_last(options)
c9c1852 @dhh Making ActiveRecord faster [skaes]
dhh authored
625 when :all then find_every(options)
626 else find_from_ids(args, options)
db045db @dhh Initial
dhh authored
627 end
628 end
3b0e1d9 @josh Prefer string core_ext inflector methods over directly accessing Inflect...
josh authored
629
98dc582 @lifo Merge docrails.
lifo authored
630 # A convenience wrapper for <tt>find(:first, *args)</tt>. You can pass in all the
631 # same arguments to this method as you can to <tt>find(:first)</tt>.
c6f2af5 @dhh Added ActiveRecord#Base.all/first/last as aliases for find(:all/:first/:...
dhh authored
632 def first(*args)
633 find(:first, *args)
634 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
635
98dc582 @lifo Merge docrails.
lifo authored
636 # A convenience wrapper for <tt>find(:last, *args)</tt>. You can pass in all the
637 # same arguments to this method as you can to <tt>find(:last)</tt>.
c6f2af5 @dhh Added ActiveRecord#Base.all/first/last as aliases for find(:all/:first/:...
dhh authored
638 def last(*args)
639 find(:last, *args)
640 end
3b0e1d9 @josh Prefer string core_ext inflector methods over directly accessing Inflect...
josh authored
641
0a6980f Let Base.all use conditions etc like first/last
David Heinemeier Hansson authored
642 # This is an alias for find(:all). You can pass in all the same arguments to this method as you can
643 # to find(:all)
644 def all(*args)
645 find(:all, *args)
646 end
3b0e1d9 @josh Prefer string core_ext inflector methods over directly accessing Inflect...
josh authored
647
98dc582 @lifo Merge docrails.
lifo authored
648 # Executes a custom SQL query against your database and returns all the results. The results will
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
649 # be returned as an array with columns requested encapsulated as attributes of the model you call
a293278 @lifo Merge docrails
lifo authored
650 # this method from. If you call <tt>Product.find_by_sql</tt> then the results will be returned in
651 # a Product object with the attributes you specified in the SQL query.
edf32ce More complete documentation for find_by_sql. Closes #7912 [fearoffish]
Marcel Molina authored
652 #
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
653 # If you call a complicated SQL query which spans multiple tables the columns specified by the
654 # SELECT will be attributes of the model, whether or not they are columns of the corresponding
edf32ce More complete documentation for find_by_sql. Closes #7912 [fearoffish]
Marcel Molina authored
655 # table.
656 #
98dc582 @lifo Merge docrails.
lifo authored
657 # The +sql+ parameter is a full SQL query as a string. It will be called as is, there will be
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
658 # no database agnostic conversions performed. This should be a last resort because using, for example,
659 # MySQL specific terms will lock you to using that particular database engine or require you to
a293278 @lifo Merge docrails
lifo authored
660 # change your call if you switch engines.
edf32ce More complete documentation for find_by_sql. Closes #7912 [fearoffish]
Marcel Molina authored
661 #
662 # ==== Examples
98dc582 @lifo Merge docrails.
lifo authored
663 # # A simple SQL query spanning multiple tables
edf32ce More complete documentation for find_by_sql. Closes #7912 [fearoffish]
Marcel Molina authored
664 # Post.find_by_sql "SELECT p.title, c.author FROM posts p, comments c WHERE p.id = c.post_id"
665 # > [#<Post:0x36bff9c @attributes={"title"=>"Ruby Meetup", "first_name"=>"Quentin"}>, ...]
666 #
667 # # You can use the same string replacement techniques as you can with ActiveRecord#find
668 # Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]
669 # > [#<Post:0x36bff9c @attributes={"first_name"=>"The Cheap Man Buys Twice"}>, ...]
db045db @dhh Initial
dhh authored
670 def find_by_sql(sql)
6e3d2a7 @jeremy Revert "Performance: freeze cached rows instead of duping"
jeremy authored
671 connection.select_all(sanitize_sql(sql), "#{name} Load").collect! { |record| instantiate(record) }
db045db @dhh Initial
dhh authored
672 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
673
dbbae5e @lifo Merge with docrails
lifo authored
674 # Returns true if a record exists in the table that matches the +id+ or
5a8f764 @smtlaissezfaire Add ActiveRecord::Base.exists? with no args [#1817 state:committed]
smtlaissezfaire authored
675 # conditions given, or false otherwise. The argument can take five forms:
dbbae5e @lifo Merge with docrails
lifo authored
676 #
677 # * Integer - Finds the record with this primary key.
678 # * String - Finds the record with a primary key corresponding to this
679 # string (such as <tt>'5'</tt>).
680 # * Array - Finds the record that matches these +find+-style conditions
681 # (such as <tt>['color = ?', 'red']</tt>).
682 # * Hash - Finds the record that matches these +find+-style conditions
683 # (such as <tt>{:color => 'red'}</tt>).
5a8f764 @smtlaissezfaire Add ActiveRecord::Base.exists? with no args [#1817 state:committed]
smtlaissezfaire authored
684 # * No args - Returns false if the table is empty, true otherwise.
971ed15 Document API for exists?'s parameter and provide examples of usage. Clos...
Marcel Molina authored
685 #
dbbae5e @lifo Merge with docrails
lifo authored
686 # For more information about specifying conditions as a Hash or Array,
687 # see the Conditions section in the introduction to ActiveRecord::Base.
971ed15 Document API for exists?'s parameter and provide examples of usage. Clos...
Marcel Molina authored
688 #
dbbae5e @lifo Merge with docrails
lifo authored
689 # Note: You can't pass in a condition as a string (like <tt>name =
690 # 'Jamie'</tt>), since it would be sanitized and then queried against
691 # the primary key column, like <tt>id = 'name = \'Jamie\''</tt>.
971ed15 Document API for exists?'s parameter and provide examples of usage. Clos...
Marcel Molina authored
692 #
693 # ==== Examples
abc895b @dhh Added new Base.find API and deprecated find_all, find_first. Added preli...
dhh authored
694 # Person.exists?(5)
58ebf30 @jeremy The exists? class method should treat a string argument as an id rather ...
jeremy authored
695 # Person.exists?('5')
8085cbf @dhh Added support for conditions on Base.exists? (closes #5689) [josh@joshpe...
dhh authored
696 # Person.exists?(:name => "David")
58ebf30 @jeremy The exists? class method should treat a string argument as an id rather ...
jeremy authored
697 # Person.exists?(['name LIKE ?', "%#{query}%"])
5a8f764 @smtlaissezfaire Add ActiveRecord::Base.exists? with no args [#1817 state:committed]
smtlaissezfaire authored
698 # Person.exists?
699 def exists?(id_or_conditions = {})
0ad24df @technoweenie Optimize ActiveRecord::Base#exists? to use #select_all instead of #find....
technoweenie authored
700 connection.select_all(
701 construct_finder_sql(
3b0e1d9 @josh Prefer string core_ext inflector methods over directly accessing Inflect...
josh authored
702 :select => "#{quoted_table_name}.#{primary_key}",
703 :conditions => expand_id_conditions(id_or_conditions),
0ad24df @technoweenie Optimize ActiveRecord::Base#exists? to use #select_all instead of #find....
technoweenie authored
704 :limit => 1
3b0e1d9 @josh Prefer string core_ext inflector methods over directly accessing Inflect...
josh authored
705 ),
0ad24df @technoweenie Optimize ActiveRecord::Base#exists? to use #select_all instead of #find....
technoweenie authored
706 "#{name} Exists"
707 ).size > 0
db045db @dhh Initial
dhh authored
708 end
abc895b @dhh Added new Base.find API and deprecated find_all, find_first. Added preli...
dhh authored
709
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
710 # Creates an object (or multiple objects) and saves it to the database, if validations pass.
a23bea7 Document API for create's attributes parameter and provide examples. Clo...
Marcel Molina authored
711 # The resulting object is returned whether the object was saved successfully to the database or not.
712 #
713 # The +attributes+ parameter can be either be a Hash or an Array of Hashes. These Hashes describe the
714 # attributes on the objects that are to be created.
715 #
716 # ==== Examples
717 # # Create a single new object
718 # User.create(:first_name => 'Jamie')
dd120ed @dhh Added block-setting of attributes for Base.create like Base.new already ...
dhh authored
719 #
a23bea7 Document API for create's attributes parameter and provide examples. Clo...
Marcel Molina authored
720 # # Create an Array of new objects
dc4eec1 @lifo Merge docrails:
lifo authored
721 # User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }])
dd120ed @dhh Added block-setting of attributes for Base.create like Base.new already ...
dhh authored
722 #
723 # # Create a single object and pass it into a block to set other attributes.
724 # User.create(:first_name => 'Jamie') do |u|
725 # u.is_admin = false
726 # end
727 #
728 # # Creating an Array of new objects using a block, where the block is executed for each object:
dc4eec1 @lifo Merge docrails:
lifo authored
729 # User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }]) do |u|
dd120ed @dhh Added block-setting of attributes for Base.create like Base.new already ...
dhh authored
730 # u.is_admin = false
3b0e1d9 @josh Prefer string core_ext inflector methods over directly accessing Inflect...
josh authored
731 # end
dd120ed @dhh Added block-setting of attributes for Base.create like Base.new already ...
dhh authored
732 def create(attributes = nil, &block)
efa81da @dhh Added the option of supplying an array of ids and attributes to Base#upd...
dhh authored
733 if attributes.is_a?(Array)
dd120ed @dhh Added block-setting of attributes for Base.create like Base.new already ...
dhh authored
734 attributes.collect { |attr| create(attr, &block) }
efa81da @dhh Added the option of supplying an array of ids and attributes to Base#upd...
dhh authored
735 else
736 object = new(attributes)
dd120ed @dhh Added block-setting of attributes for Base.create like Base.new already ...
dhh authored
737 yield(object) if block_given?
efa81da @dhh Added the option of supplying an array of ids and attributes to Base#upd...
dhh authored
738 object.save
739 object
740 end
db045db @dhh Initial
dhh authored
741 end
742
1b7a18d Document options and add examples for update. Closes #7985 [fearoffish]
Marcel Molina authored
743 # Updates an object (or multiple objects) and saves it to the database, if validations pass.
744 # The resulting object is returned whether the object was saved successfully to the database or not.
5e99422 @dhh Updated docs (closes #3799) [ruby@bobsilva.com]
dhh authored
745 #
a293278 @lifo Merge docrails
lifo authored
746 # ==== Parameters
5e99422 @dhh Updated docs (closes #3799) [ruby@bobsilva.com]
dhh authored
747 #
dc4eec1 @lifo Merge docrails:
lifo authored
748 # * +id+ - This should be the id or an array of ids to be updated.
18eb80c @lifo Merge docrails
lifo authored
749 # * +attributes+ - This should be a hash of attributes to be set on the object, or an array of hashes.
1b7a18d Document options and add examples for update. Closes #7985 [fearoffish]
Marcel Molina authored
750 #
751 # ==== Examples
752 #
753 # # Updating one record:
18eb80c @lifo Merge docrails
lifo authored
754 # Person.update(15, :user_name => 'Samuel', :group => 'expert')
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
755 #
1b7a18d Document options and add examples for update. Closes #7985 [fearoffish]
Marcel Molina authored
756 # # Updating multiple records:
dc4eec1 @lifo Merge docrails:
lifo authored
757 # people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
5e99422 @dhh Updated docs (closes #3799) [ruby@bobsilva.com]
dhh authored
758 # Person.update(people.keys, people.values)
db045db @dhh Initial
dhh authored
759 def update(id, attributes)
efa81da @dhh Added the option of supplying an array of ids and attributes to Base#upd...
dhh authored
760 if id.is_a?(Array)
761 idx = -1
8b5f4e4 @jeremy Ruby 1.9 compat: fix warnings, shadowed block vars, and unitialized inst...
jeremy authored
762 id.collect { |one_id| idx += 1; update(one_id, attributes[idx]) }
efa81da @dhh Added the option of supplying an array of ids and attributes to Base#upd...
dhh authored
763 else
764 object = find(id)
765 object.update_attributes(attributes)
766 object
767 end
db045db @dhh Initial
dhh authored
768 end
769
39e1ac6 @lifo Merge docrails
lifo authored
770 # Deletes the row with a primary key matching the +id+ argument, using a
771 # SQL +DELETE+ statement, and returns the number of rows deleted. Active
772 # Record objects are not instantiated, so the object's callbacks are not
773 # executed, including any <tt>:dependent</tt> association options or
774 # Observer methods.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
775 #
39e1ac6 @lifo Merge docrails
lifo authored
776 # You can delete multiple rows at once by passing an Array of <tt>id</tt>s.
6a45e01 Document options and add examples for delete. Closes #7986 [fearoffish]
Marcel Molina authored
777 #
39e1ac6 @lifo Merge docrails
lifo authored
778 # Note: Although it is often much faster than the alternative,
779 # <tt>#destroy</tt>, skipping callbacks might bypass business logic in
780 # your application that ensures referential integrity or performs other
781 # essential jobs.
6a45e01 Document options and add examples for delete. Closes #7986 [fearoffish]
Marcel Molina authored
782 #
783 # ==== Examples
784 #
39e1ac6 @lifo Merge docrails
lifo authored
785 # # Delete a single row
6a45e01 Document options and add examples for delete. Closes #7986 [fearoffish]
Marcel Molina authored
786 # Todo.delete(1)
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
787 #
39e1ac6 @lifo Merge docrails
lifo authored
788 # # Delete multiple rows
789 # Todo.delete([2,3,4])
648b8fd @dhh Added Base.destroy and Base.delete to remove records without holding a r...
dhh authored
790 def delete(id)
98165fd @jeremy Consistently quote primary key column names. Closes #7763.
jeremy authored
791 delete_all([ "#{connection.quote_column_name(primary_key)} IN (?)", id ])
648b8fd @dhh Added Base.destroy and Base.delete to remove records without holding a r...
dhh authored
792 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
793
ed69b38 Document options and add examples for destroy. Closes #7988 [fearoffish]
Marcel Molina authored
794 # Destroy an object (or multiple objects) that has the given id, the object is instantiated first,
795 # therefore all callbacks and filters are fired off before the object is deleted. This method is
796 # less efficient than ActiveRecord#delete but allows cleanup methods and other actions to be run.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
797 #
798 # This essentially finds the object (or multiple objects) with the given id, creates a new object
ed69b38 Document options and add examples for destroy. Closes #7988 [fearoffish]
Marcel Molina authored
799 # from the attributes, and then calls destroy on it.
800 #
a293278 @lifo Merge docrails
lifo authored
801 # ==== Parameters
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
802 #
dc4eec1 @lifo Merge docrails:
lifo authored
803 # * +id+ - Can be either an Integer or an Array of Integers.
ed69b38 Document options and add examples for destroy. Closes #7988 [fearoffish]
Marcel Molina authored
804 #
805 # ==== Examples
806 #
807 # # Destroy a single object
808 # Todo.destroy(1)
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
809 #
ed69b38 Document options and add examples for destroy. Closes #7988 [fearoffish]
Marcel Molina authored
810 # # Destroy multiple objects
811 # todos = [1,2,3]
812 # Todo.destroy(todos)
648b8fd @dhh Added Base.destroy and Base.delete to remove records without holding a r...
dhh authored
813 def destroy(id)
8b5f4e4 @jeremy Ruby 1.9 compat: fix warnings, shadowed block vars, and unitialized inst...
jeremy authored
814 if id.is_a?(Array)
815 id.map { |one_id| destroy(one_id) }
816 else
817 find(id).destroy
818 end
648b8fd @dhh Added Base.destroy and Base.delete to remove records without holding a r...
dhh authored
819 end
820
4f1d353 Document options and add examples for update_all. Closes #7990 [fearoffi...
Marcel Molina authored
821 # Updates all records with details given if they match a set of conditions supplied, limits and order can
6ef3546 @lifo Merge docrails
lifo authored
822 # also be supplied. This method constructs a single SQL UPDATE statement and sends it straight to the
f97832b @lifo Merge docrails
lifo authored
823 # database. It does not instantiate the involved models and it does not trigger Active Record callbacks
824 # or validations.
a38f28f @jeremy Base.update_all :order and :limit options. Useful for MySQL updates that...
jeremy authored
825 #
a293278 @lifo Merge docrails
lifo authored
826 # ==== Parameters
4f1d353 Document options and add examples for update_all. Closes #7990 [fearoffi...
Marcel Molina authored
827 #
f97832b @lifo Merge docrails
lifo authored
828 # * +updates+ - A string, array, or hash representing the SET part of an SQL statement.
829 # * +conditions+ - A string, array, or hash representing the WHERE part of an SQL statement. See conditions in the intro.
6ef3546 @lifo Merge docrails
lifo authored
830 # * +options+ - Additional options are <tt>:limit</tt> and <tt>:order</tt>, see the examples for usage.
4f1d353 Document options and add examples for update_all. Closes #7990 [fearoffi...
Marcel Molina authored
831 #
832 # ==== Examples
833 #
f97832b @lifo Merge docrails
lifo authored
834 # # Update all customers with the given attributes
835 # Customer.update_all :wants_email => true
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
836 #
f97832b @lifo Merge docrails
lifo authored
837 # # Update all books with 'Rails' in their title
838 # Book.update_all "author = 'David'", "title LIKE '%Rails%'"
4f1d353 Document options and add examples for update_all. Closes #7990 [fearoffi...
Marcel Molina authored
839 #
f97832b @lifo Merge docrails
lifo authored
840 # # Update all avatars migrated more than a week ago
841 # Avatar.update_all ['migrated_at = ?, Time.now.utc], ['migrated_at > ?', 1.week.ago]
842 #
843 # # Update all books that match our conditions, but limit it to 5 ordered by date
844 # Book.update_all "author = 'David'", "title LIKE '%Rails%'", :order => 'created_at', :limit => 5
a38f28f @jeremy Base.update_all :order and :limit options. Useful for MySQL updates that...
jeremy authored
845 def update_all(updates, conditions = nil, options = {})
ebe3a0d @jeremy More thoroughly quote table names. Exposes some issues with sqlite2 adap...
jeremy authored
846 sql = "UPDATE #{quoted_table_name} SET #{sanitize_sql_for_assignment(updates)} "
7c9851d @tarmo Support :limit on update_all so that has_many with :limit can be safely ...
tarmo authored
847
a38f28f @jeremy Base.update_all :order and :limit options. Useful for MySQL updates that...
jeremy authored
848 scope = scope(:find)
7c9851d @tarmo Support :limit on update_all so that has_many with :limit can be safely ...
tarmo authored
849
850 select_sql = ""
851 add_conditions!(select_sql, conditions, scope)
852
853 if options.has_key?(:limit) || (scope && scope[:limit])
854 # Only take order from scope if limit is also provided by scope, this
855 # is useful for updating a has_many association with a limit.
856 add_order!(select_sql, options[:order], scope)
857
858 add_limit!(select_sql, options, scope)
859 sql.concat(connection.limited_update_conditions(select_sql, quoted_table_name, connection.quote_column_name(primary_key)))
860 else
861 add_order!(select_sql, options[:order], nil)
862 sql.concat(select_sql)
863 end
864
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
865 connection.update(sql, "#{name} Update")
db045db @dhh Initial
dhh authored
866 end
0d2db8a @dhh Added Base.update_collection that can update an array of id/attribute pa...
dhh authored
867
39e1ac6 @lifo Merge docrails
lifo authored
868 # Destroys the records matching +conditions+ by instantiating each
869 # record and calling its +destroy+ method. Each object's callbacks are
870 # executed (including <tt>:dependent</tt> association options and
871 # +before_destroy+/+after_destroy+ Observer methods). Returns the
872 # collection of objects that were destroyed; each will be frozen, to
873 # reflect that no changes should be made (since they can't be
874 # persisted).
875 #
876 # Note: Instantiation, callback execution, and deletion of each
877 # record can be time consuming when you're removing many records at
878 # once. It generates at least one SQL +DELETE+ query per record (or
879 # possibly more, to enforce your callbacks). If you want to delete many
880 # rows quickly, without concern for their associations or callbacks, use
881 # +delete_all+ instead.
4b055a4 @jeremy Update destroy_all and delete_all documentation to better describe their...
jeremy authored
882 #
a293278 @lifo Merge docrails
lifo authored
883 # ==== Parameters
4b055a4 @jeremy Update destroy_all and delete_all documentation to better describe their...
jeremy authored
884 #
39e1ac6 @lifo Merge docrails
lifo authored
885 # * +conditions+ - A string, array, or hash that specifies which records
886 # to destroy. If omitted, all records are destroyed. See the
887 # Conditions section in the introduction to ActiveRecord::Base for
888 # more information.
4b055a4 @jeremy Update destroy_all and delete_all documentation to better describe their...
jeremy authored
889 #
39e1ac6 @lifo Merge docrails
lifo authored
890 # ==== Examples
4b055a4 @jeremy Update destroy_all and delete_all documentation to better describe their...
jeremy authored
891 #
a293278 @lifo Merge docrails
lifo authored
892 # Person.destroy_all("last_login < '2004-04-04'")
39e1ac6 @lifo Merge docrails
lifo authored
893 # Person.destroy_all(:status => "inactive")
db045db @dhh Initial
dhh authored
894 def destroy_all(conditions = nil)
3dfa56c @dhh Updated all references to the old find_first and find_all to use the new...
dhh authored
895 find(:all, :conditions => conditions).each { |object| object.destroy }
db045db @dhh Initial
dhh authored
896 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
897
4b055a4 @jeremy Update destroy_all and delete_all documentation to better describe their...
jeremy authored
898 # Deletes the records matching +conditions+ without instantiating the records first, and hence not
6ef3546 @lifo Merge docrails
lifo authored
899 # calling the +destroy+ method nor invoking callbacks. This is a single SQL DELETE statement that
a293278 @lifo Merge docrails
lifo authored
900 # goes straight to the database, much more efficient than +destroy_all+. Be careful with relations
53cd102 @lifo Merge with docrails
lifo authored
901 # though, in particular <tt>:dependent</tt> rules defined on associations are not honored. Returns
902 # the number of rows affected.
4b055a4 @jeremy Update destroy_all and delete_all documentation to better describe their...
jeremy authored
903 #
a293278 @lifo Merge docrails
lifo authored
904 # ==== Parameters
4b055a4 @jeremy Update destroy_all and delete_all documentation to better describe their...
jeremy authored
905 #
dc4eec1 @lifo Merge docrails:
lifo authored
906 # * +conditions+ - Conditions are specified the same way as with +find+ method.
4b055a4 @jeremy Update destroy_all and delete_all documentation to better describe their...
jeremy authored
907 #
908 # ==== Example
909 #
a293278 @lifo Merge docrails
lifo authored
910 # Post.delete_all("person_id = 5 AND (category = 'Something' OR category = 'Else')")
911 # Post.delete_all(["person_id = ? AND (category = ? OR category = ?)", 5, 'Something', 'Else'])
4b055a4 @jeremy Update destroy_all and delete_all documentation to better describe their...
jeremy authored
912 #
a293278 @lifo Merge docrails
lifo authored
913 # Both calls delete the affected posts all at once with a single DELETE statement. If you need to destroy dependent
6ef3546 @lifo Merge docrails
lifo authored
914 # associations or call your <tt>before_*</tt> or +after_destroy+ callbacks, use the +destroy_all+ method instead.
db045db @dhh Initial
dhh authored
915 def delete_all(conditions = nil)
9b6207c @jeremy Quote table names. Defaults to column quoting. Closes #4593.
jeremy authored
916 sql = "DELETE FROM #{quoted_table_name} "
c9c1852 @dhh Making ActiveRecord faster [skaes]
dhh authored
917 add_conditions!(sql, conditions, scope(:find))
db045db @dhh Initial
dhh authored
918 connection.delete(sql, "#{name} Delete all")
919 end
920
921 # Returns the result of an SQL statement that should only include a COUNT(*) in the SELECT part.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
922 # The use of this method should be restricted to complicated SQL queries that can't be executed
ee614d6 Add documentation caveat about when to use count_by_sql. Closes #8090. [...
Marcel Molina authored
923 # using the ActiveRecord::Calculations class methods. Look into those before using this.
924 #
a293278 @lifo Merge docrails
lifo authored
925 # ==== Parameters
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
926 #
dc4eec1 @lifo Merge docrails:
lifo authored
927 # * +sql+ - An SQL statement which should return a count query from the database, see the example below.
ee614d6 Add documentation caveat about when to use count_by_sql. Closes #8090. [...
Marcel Molina authored
928 #
929 # ==== Examples
930 #
e17bf81 @jamis Fix typo in count_by_sql documentation #1969 [Alexey Verkhovsky]
jamis authored
931 # Product.count_by_sql "SELECT COUNT(*) FROM sales s, customers c WHERE s.customer_id = c.id"
db045db @dhh Initial
dhh authored
932 def count_by_sql(sql)
a775cb1 @dhh Added the option for sanitizing find_by_sql and the offset parts in regu...
dhh authored
933 sql = sanitize_conditions(sql)
caaf40d @dhh Added AbstractAdapter#select_value and AbstractAdapter#select_values as ...
dhh authored
934 connection.select_value(sql, "#{name} Count").to_i
db045db @dhh Initial
dhh authored
935 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
936
8375237 @jamis Made increment_counter/decrement_counter play nicely with optimistic loc...
jamis authored
937 # A generic "counter updater" implementation, intended primarily to be
938 # used by increment_counter and decrement_counter, but which may also
939 # be useful on its own. It simply does a direct SQL update for the record
940 # with the given ID, altering the given hash of counters by the amount
941 # given by the corresponding value:
942 #
a293278 @lifo Merge docrails
lifo authored
943 # ==== Parameters
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
944 #
7487196 @lifo Add array id support to Model.update_counters. [#1254 state:resolved] [C...
lifo authored
945 # * +id+ - The id of the object you wish to update a counter on or an Array of ids.
dc4eec1 @lifo Merge docrails:
lifo authored
946 # * +counters+ - An Array of Hashes containing the names of the fields
947 # to update as keys and the amount to update the field by as values.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
948 #
6bd7d30 Document options for update_counters. Closes #8091 [fearoffish]
Marcel Molina authored
949 # ==== Examples
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
950 #
951 # # For the Post with id of 5, decrement the comment_count by 1, and
6bd7d30 Document options for update_counters. Closes #8091 [fearoffish]
Marcel Molina authored
952 # # increment the action_count by 1
8375237 @jamis Made increment_counter/decrement_counter play nicely with optimistic loc...
jamis authored
953 # Post.update_counters 5, :comment_count => -1, :action_count => 1
6bd7d30 Document options for update_counters. Closes #8091 [fearoffish]
Marcel Molina authored
954 # # Executes the following SQL:
8375237 @jamis Made increment_counter/decrement_counter play nicely with optimistic loc...
jamis authored
955 # # UPDATE posts
956 # # SET comment_count = comment_count - 1,
957 # # action_count = action_count + 1
958 # # WHERE id = 5
7487196 @lifo Add array id support to Model.update_counters. [#1254 state:resolved] [C...
lifo authored
959 #
960 # # For the Posts with id of 10 and 15, increment the comment_count by 1
961 # Post.update_counters [10, 15], :comment_count => 1
962 # # Executes the following SQL:
963 # # UPDATE posts
964 # # SET comment_count = comment_count + 1,
965 # # WHERE id IN (10, 15)
8375237 @jamis Made increment_counter/decrement_counter play nicely with optimistic loc...
jamis authored
966 def update_counters(id, counters)
967 updates = counters.inject([]) { |list, (counter_name, increment)|
968 sign = increment < 0 ? "-" : "+"
459e581 @miloops update_counters should update nil values.
miloops authored
969 list << "#{connection.quote_column_name(counter_name)} = COALESCE(#{connection.quote_column_name(counter_name)}, 0) #{sign} #{increment.abs}"
8375237 @jamis Made increment_counter/decrement_counter play nicely with optimistic loc...
jamis authored
970 }.join(", ")
7487196 @lifo Add array id support to Model.update_counters. [#1254 state:resolved] [C...
lifo authored
971
972 if id.is_a?(Array)
973 ids_list = id.map {|i| quote_value(i)}.join(', ')
974 condition = "IN (#{ids_list})"
975 else
976 condition = "= #{quote_value(id)}"
977 end
978
979 update_all(updates, "#{connection.quote_column_name(primary_key)} #{condition}")
8375237 @jamis Made increment_counter/decrement_counter play nicely with optimistic loc...
jamis authored
980 end
981
15dc567 Also add documentation enhancements for increment_counter. Closes #8092....
Marcel Molina authored
982 # Increment a number field by one, usually representing a count.
983 #
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
984 # This is used for caching aggregate values, so that they don't need to be computed every time.
985 # For example, a DiscussionBoard may cache post_count and comment_count otherwise every time the board is
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobSilv...
Marcel Molina authored
986 # shown it would have to run an SQL query to find how many posts and comments there are.
15dc567 Also add documentation enhancements for increment_counter. Closes #8092....
Marcel Molina authored
987 #
a293278 @lifo Merge docrails
lifo authored
988 # ==== Parameters
15dc567 Also add documentation enhancements for increment_counter. Closes #8092....
Marcel Molina authored
989 #
dc4eec1 @lifo Merge docrails:
lifo authored
990 # * +counter_name+ - The name of the field that should be incremented.
991 # * +id+ - The id of the object that should be incremented.
15dc567 Also add documentation enhancements for increment_counter. Closes #8092....
Marcel Molina authored
992 #
993 # ==== Examples
994 #
995 # # Increment the post_count column for the record with an id of 5
996 # DiscussionBoard.increment_counter(:post_count, 5)
db045db @dhh Initial
dhh authored
997 def increment_counter(counter_name, id)
8375237 @jamis Made increment_counter/decrement_counter play nicely with optimistic loc...
jamis authored
998 update_counters(id, counter_name => 1)
db045db @dhh Initial
dhh authored
999 end
1000
5bd3570 Enhance documentation for decrement_counter. Closes #8093. [fearoffish]
Marcel Molina authored
1001 # Decrement a number field by one, usually representing a count.
1002 #
1003 # This works the same as increment_counter but reduces the column value by 1 instead of increasing it.
1004 #
a293278 @lifo Merge docrails
lifo authored
1005 # ==== Parameters
5bd3570 Enhance documentation for decrement_counter. Closes #8093. [fearoffish]
Marcel Molina authored
1006 #
dc4eec1 @lifo Merge docrails:
lifo authored
1007 # * +counter_name+ - The name of the field that should be decremented.
1008 # * +id+ - The id of the object that should be decremented.
5bd3570 Enhance documentation for decrement_counter. Closes #8093. [fearoffish]
Marcel Molina authored
1009 #
1010 # ==== Examples
1011 #
1012 # # Decrement the post_count column for the record with an id of 5
1013 # DiscussionBoard.decrement_counter(:post_count, 5)
db045db @dhh Initial
dhh authored
1014 def decrement_counter(counter_name, id)
8375237 @jamis Made increment_counter/decrement_counter play nicely with optimistic loc...
jamis authored
1015 update_counters(id, counter_name => -1)
db045db @dhh Initial
dhh authored
1016 end
1017
98dc582 @lifo Merge docrails.
lifo authored
1018 # Attributes named in this macro are protected from mass-assignment,
1019 # such as <tt>new(attributes)</tt>,
1020 # <tt>update_attributes(attributes)</tt>, or
1021 # <tt>attributes=(attributes)</tt>.
1022 #
1023 # Mass-assignment to these attributes will simply be ignored, to assign
1024 # to them you can use direct writer methods. This is meant to protect
1025 # sensitive attributes from being overwritten by malicious users
1026 # tampering with URLs or forms.
db045db @dhh Initial
dhh authored
1027 #
1028 # class Customer < ActiveRecord::Base
1029 # attr_protected :credit_rating
1030 # end
1031 #
1032 # customer = Customer.new("name" => David, "credit_rating" => "Excellent")
1033 # customer.credit_rating # => nil
1034 # customer.attributes = { "description" => "Jolly fellow", "credit_rating" => "Superb" }
1035 # customer.credit_rating # => nil
1036 #
1037 # customer.credit_rating = "Average"
1038 # customer.credit_rating # => "Average"
d761ac4 Add docs explaining how to protect all attributes using attr_accessible ...
Marcel Molina authored
1039 #
98dc582 @lifo Merge docrails.
lifo authored
1040 # To start from an all-closed default and enable attributes as needed,
1041 # have a look at +attr_accessible+.
db045db @dhh Initial
dhh authored
1042 def attr_protected(*attributes)
288e947 @clemens Some performance goodness for inheritable attributes.
clemens authored
1043 write_inheritable_attribute(:attr_protected, Set.new(attributes.map(&:to_s)) + (protected_attributes || []))
db045db @dhh Initial
dhh authored
1044 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
1045
098fa94 @dhh Fixed documentation snafus #575, #576, #577, #585
dhh authored
1046 # Returns an array of all the attributes that have been protected from mass-assignment.
db045db @dhh Initial
dhh authored
1047 def protected_attributes # :nodoc:
288e947 @clemens Some performance goodness for inheritable attributes.
clemens authored
1048 read_inheritable_attribute(:attr_protected)
db045db @dhh Initial
dhh authored
1049 end
1050
98dc582 @lifo Merge docrails.
lifo authored
1051 # Specifies a white list of model attributes that can be set via
1052 # mass-assignment, such as <tt>new(attributes)</tt>,
1053 # <tt>update_attributes(attributes)</tt>, or
1054 # <tt>attributes=(attributes)</tt>
f770b82 Enhance explanation with more examples for attr_accessible macro. Closes...
Marcel Molina authored
1055 #
98dc582 @lifo Merge docrails.
lifo authored
1056 # This is the opposite of the +attr_protected+ macro: Mass-assignment
1057 # will only set attributes in this list, to assign to the rest of
1058 # attributes you can use direct writer methods. This is meant to protect
1059 # sensitive attributes from being overwritten by malicious users
1060 # tampering with URLs or forms. If you'd rather start from an all-open
1061 # default and restrict attributes as needed, have a look at
1062 # +attr_protected+.
d761ac4 Add docs explaining how to protect all attributes using attr_accessible ...
Marcel Molina authored
1063 #
1064 # class Customer < ActiveRecord::Base
f770b82 Enhance explanation with more examples for attr_accessible macro. Closes...
Marcel Molina authored
1065 # attr_accessible :name, :nickname
d761ac4 Add docs explaining how to protect all attributes using attr_accessible ...
Marcel Molina authored
1066 # end
1067 #
f770b82 Enhance explanation with more examples for attr_accessible macro. Closes...
Marcel Molina authored
1068 # customer = Customer.new(:name => "David", :nickname => "Dave", :credit_rating => "Excellent")
1069 # customer.credit_rating # => nil
1070 # customer.attributes = { :name => "Jolly fellow", :credit_rating => "Superb" }
1071 # customer.credit_rating # => nil
d761ac4 Add docs explaining how to protect all attributes using attr_accessible ...
Marcel Molina authored
1072 #
f770b82 Enhance explanation with more examples for attr_accessible macro. Closes...
Marcel Molina authored
1073 # customer.credit_rating = "Average"
1074 # customer.credit_rating # => "Average"
db045db @dhh Initial
dhh authored
1075 def attr_accessible(*attributes)
288e947 @clemens Some performance goodness for inheritable attributes.
clemens authored
1076 write_inheritable_attribute(:attr_accessible, Set.new(attributes.map(&:to_s)) + (accessible_attributes || []))
db045db