Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100755 2707 lines (2413 sloc) 119.931 kB
db045db @dhh Initial
dhh authored
1 require 'yaml'
aabf909 @jeremy Correct reader method generation for primary key attribute: handle ca…
jeremy authored
2 require 'set'
db045db @dhh Initial
dhh authored
3
4 module ActiveRecord #:nodoc:
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
5 # Generic ActiveRecord exception class.
6 class ActiveRecordError < StandardError
db045db @dhh Initial
dhh authored
7 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
8
9 # Raised when the single-table inheritance mechanism failes to locate the subclass
10 # (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 wi…
dhh authored
11 class SubclassNotFound < ActiveRecordError #:nodoc:
12 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
13
64092de @fxn Improve documentation coverage and markup
fxn authored
14 # Raised when an object assigned to an association has an incorrect type.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
15 #
64092de @fxn Improve documentation coverage and markup
fxn authored
16 # class Ticket < ActiveRecord::Base
17 # has_many :patches
18 # end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
19 #
64092de @fxn Improve documentation coverage and markup
fxn authored
20 # class Patch < ActiveRecord::Base
21 # belongs_to :ticket
22 # end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
23 #
64092de @fxn Improve documentation coverage and markup
fxn authored
24 # # Comments are not patches, this assignment raises AssociationTypeMismatch.
25 # @ticket.patches << Comment.new(:content => "Please attach tests to your patch.")
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
26 class AssociationTypeMismatch < ActiveRecordError
db045db @dhh Initial
dhh authored
27 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
28
29 # Raised when unserialized object's type mismatches one specified for serializable field.
30 class SerializationTypeMismatch < ActiveRecordError
db045db @dhh Initial
dhh authored
31 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
32
33 # Raised when adapter not specified on connection (or configuration file config/database.yml misses adapter field).
34 class AdapterNotSpecified < ActiveRecordError
db045db @dhh Initial
dhh authored
35 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
36
37 # Raised when ActiveRecord cannot find database adapter specified in config/database.yml or programmatically.
38 class AdapterNotFound < ActiveRecordError
db045db @dhh Initial
dhh authored
39 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
40
41 # Raised when connection to the database could not been established (for example when connection= is given a nil object).
42 class ConnectionNotEstablished < ActiveRecordError
db045db @dhh Initial
dhh authored
43 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
44
45 # Raised when ActiveRecord cannot find record by given id or set of ids.
46 class RecordNotFound < ActiveRecordError
db045db @dhh Initial
dhh authored
47 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
48
49 # Raised by ActiveRecord::Base.save! and ActiveRecord::Base.create! methods when record cannot be
50 # saved because record is invalid.
51 class RecordNotSaved < ActiveRecordError
4c7555a @dhh Fixed that Base.save should always return false if the save didn't su…
dhh authored
52 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
53
54 # 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).
55 class StatementInvalid < ActiveRecordError
db045db @dhh Initial
dhh authored
56 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
57
64092de @fxn Improve documentation coverage and markup
fxn authored
58 # 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
59 # does not match number of expected variables.
60 #
64092de @fxn Improve documentation coverage and markup
fxn authored
61 # For example, in
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
62 #
64092de @fxn Improve documentation coverage and markup
fxn authored
63 # Location.find :all, :conditions => ["lat = ? AND lng = ?", 53.7362]
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
64 #
64092de @fxn Improve documentation coverage and markup
fxn authored
65 # two placeholders are given but only one variable to fill them.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
66 class PreparedStatementInvalid < ActiveRecordError
554597d @dhh Added named bind-style variable interpolation #281 [Michael Koziarski]
dhh authored
67 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
68
69 # Raised on attempt to save stale record. Record is stale when it's being saved in another query after
70 # instantiation, for example, when two users edit the same wiki page and one starts editing and saves
71 # the page before the other.
72 #
73 # Read more about optimistic locking in +ActiveRecord::Locking+ module RDoc.
74 class StaleObjectError < ActiveRecordError
fbf9281 @dhh Added automated optimistic locking if the field lock_version is prese…
dhh authored
75 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
76
77 # Raised when association is being configured improperly or
78 # user tries to use offset and limit together with has_many or has_and_belongs_to_many associations.
79 class ConfigurationError < ActiveRecordError
5b9b904 @dhh Added support for limit and offset with eager loading of has_one and …
dhh authored
80 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
81
82 # Raised on attempt to update record that is instantiated as read only.
83 class ReadOnlyRecord < ActiveRecordError
64fcb75 @jeremy r3618@sedna: jeremy | 2005-10-14 12:06:03 -0700
jeremy authored
84 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
85
86 # Used by ActiveRecord transaction mechanism to distinguish rollback from other exceptional situations.
87 # You can use it to roll your transaction back explicitly in the block passed to +transaction+ method.
88 class Rollback < ActiveRecordError
5b2e8b1 @technoweenie Fix that ActiveRecord would create attribute methods and override cus…
technoweenie authored
89 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
90
91 # Raised when attribute has a name reserved by ActiveRecord (when attribute has name of one of ActiveRecord instance methods).
92 class DangerousAttributeError < ActiveRecordError
ebbe4fb @NZKoz Replace the transaction {|transaction|..} semantics with a new Except…
NZKoz authored
93 end
84a14f2 @jeremy Raise ProtectedAttributeAssignmentError in development and test envir…
jeremy authored
94
dc4eec1 @lifo Merge docrails:
lifo authored
95 # Raised when you've tried to access a column which wasn't loaded by your finder.
96 # Typically this is because <tt>:select</tt> has been specified.
5b801b5 @NZKoz Change the implementation of ActiveRecord's attribute reader and writ…
NZKoz authored
97 class MissingAttributeError < NoMethodError
98 end
e48b062 @jeremy Sanitize Base#inspect. Closes #8392.
jeremy authored
99
dc4eec1 @lifo Merge docrails:
lifo authored
100 # Raised when an error occured while doing a mass assignment to an attribute through the
101 # <tt>attributes=</tt> method. The exception has an +attribute+ property that is the name of the
102 # offending attribute.
103 class AttributeAssignmentError < ActiveRecordError
d2fefbe @dhh Added MultiparameterAssignmentErrors and AttributeAssignmentError exc…
dhh authored
104 attr_reader :exception, :attribute
105 def initialize(message, exception, attribute)
106 @exception = exception
107 @attribute = attribute
108 @message = message
109 end
110 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
111
dc4eec1 @lifo Merge docrails:
lifo authored
112 # Raised when there are multiple errors while doing a mass assignment through the +attributes+
113 # method. The exception has an +errors+ property that contains an array of AttributeAssignmentError
114 # objects, each corresponding to the error while assigning to an attribute.
115 class MultiparameterAssignmentErrors < ActiveRecordError
d2fefbe @dhh Added MultiparameterAssignmentErrors and AttributeAssignmentError exc…
dhh authored
116 attr_reader :errors
117 def initialize(errors)
118 @errors = errors
119 end
120 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
121
2948910 Misc doc fixes (typos/grammar/etc.). Closes #2430.
Marcel Molina authored
122 # Active Record objects don't specify their attributes directly, but rather infer them from the table definition with
db045db @dhh Initial
dhh authored
123 # which they're linked. Adding, removing, and changing attributes and their type is done directly in the database. Any change
124 # 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
125 # database table will happen automatically in most common cases, but can be overwritten for the uncommon ones.
126 #
db045db @dhh Initial
dhh authored
127 # 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
128 #
db045db @dhh Initial
dhh authored
129 # == Creation
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
130 #
2948910 Misc doc fixes (typos/grammar/etc.). Closes #2430.
Marcel Molina authored
131 # 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 [BobS…
Marcel Molina authored
132 # 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
133 #
0591c53 @dhh Made the dynamic finders use the new find API and updated the example…
dhh authored
134 # user = User.new(:name => "David", :occupation => "Code Artist")
db045db @dhh Initial
dhh authored
135 # user.name # => "David"
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
136 #
db045db @dhh Initial
dhh authored
137 # You can also use block initialization:
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
138 #
db045db @dhh Initial
dhh authored
139 # user = User.new do |u|
140 # u.name = "David"
141 # u.occupation = "Code Artist"
142 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
143 #
db045db @dhh Initial
dhh authored
144 # 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
145 #
db045db @dhh Initial
dhh authored
146 # user = User.new
147 # user.name = "David"
148 # user.occupation = "Code Artist"
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
149 #
db045db @dhh Initial
dhh authored
150 # == Conditions
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
151 #
c5ec16e @dhh Added simple hash conditions to find that'll just convert hash to an …
dhh authored
152 # Conditions can either be specified as a string, array, or hash representing the WHERE-part of an SQL statement.
db045db @dhh Initial
dhh authored
153 # 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 …
dhh authored
154 # 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 #…
jeremy authored
155 # only equality and range is possible. Examples:
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
156 #
48052d7 @jeremy to_xml fixes, features, and speedup. Closes #4989.
jeremy authored
157 # class User < ActiveRecord::Base
db045db @dhh Initial
dhh authored
158 # def self.authenticate_unsafely(user_name, password)
3dfa56c @dhh Updated all references to the old find_first and find_all to use the …
dhh authored
159 # find(:first, :conditions => "user_name = '#{user_name}' AND password = '#{password}'")
db045db @dhh Initial
dhh authored
160 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
161 #
db045db @dhh Initial
dhh authored
162 # def self.authenticate_safely(user_name, password)
3dfa56c @dhh Updated all references to the old find_first and find_all to use the …
dhh authored
163 # find(:first, :conditions => [ "user_name = ? AND password = ?", user_name, password ])
db045db @dhh Initial
dhh authored
164 # end
c5ec16e @dhh Added simple hash conditions to find that'll just convert hash to an …
dhh authored
165 #
166 # def self.authenticate_safely_simply(user_name, password)
167 # find(:first, :conditions => { :user_name => user_name, :password => password })
168 # end
db045db @dhh Initial
dhh authored
169 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
170 #
2575b3b @dhh Added extra words of caution for guarding against SQL-injection attacks
dhh authored
171 # 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 [BobS…
Marcel Molina authored
172 # 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
173 # <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 …
dhh authored
174 # 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
175 #
5cd38ca @dhh Added documentation about named bind variables
dhh authored
176 # 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
177 # 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
178 # the question marks with symbols and supplying a hash with values for the matching symbol keys:
179 #
a7e6e00 Documentation for find incorrectly omits the :conditions option from …
Marcel Molina authored
180 # Company.find(:first, :conditions => [
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
181 # "id = :id AND name = :name AND division = :division AND created_at > :accounting_date",
5cd38ca @dhh Added documentation about named bind variables
dhh authored
182 # { :id => 3, :name => "37signals", :division => "First", :accounting_date => '2005-01-01' }
183 # ])
184 #
c5ec16e @dhh Added simple hash conditions to find that'll just convert hash to an …
dhh authored
185 # Similarly, a simple hash without a statement will generate conditions based on equality with the SQL AND
186 # operator. For instance:
187 #
188 # Student.find(:all, :conditions => { :first_name => "Harvey", :status => 1 })
189 # Student.find(:all, :conditions => params[:student])
190 #
2876707 @jeremy Pass a range in :conditions to use the SQL BETWEEN operator. Closes #…
jeremy authored
191 # A range may be used in the hash to use the SQL BETWEEN operator:
192 #
193 # Student.find(:all, :conditions => { :grade => 9..12 })
c5ec16e @dhh Added simple hash conditions to find that'll just convert hash to an …
dhh authored
194 #
aa4af60 @lifo Improve documentation.
lifo authored
195 # An array may be used in the hash to use the SQL IN operator:
196 #
197 # Student.find(:all, :conditions => { :grade => [9,11,12] })
198 #
db045db @dhh Initial
dhh authored
199 # == Overwriting default accessors
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
200 #
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobS…
Marcel Molina authored
201 # All column values are automatically available through basic accessors on the Active Record object, but sometimes you
202 # want to specialize this behavior. This can be done by overwriting the default accessors (using the same
203 # name as the attribute) and calling read_attribute(attr_name) and write_attribute(attr_name, value) to actually change things.
db045db @dhh Initial
dhh authored
204 # Example:
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
205 #
db045db @dhh Initial
dhh authored
206 # class Song < ActiveRecord::Base
207 # # 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
208 #
db045db @dhh Initial
dhh authored
209 # def length=(minutes)
64092de @fxn Improve documentation coverage and markup
fxn authored
210 # write_attribute(:length, minutes.to_i * 60)
db045db @dhh Initial
dhh authored
211 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
212 #
db045db @dhh Initial
dhh authored
213 # def length
0591c53 @dhh Made the dynamic finders use the new find API and updated the example…
dhh authored
214 # read_attribute(:length) / 60
db045db @dhh Initial
dhh authored
215 # end
216 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
217 #
e3b49c0 @dhh Fixed spelling errors (closes #9706) [tarmo/rmm5t]
dhh authored
218 # You can alternatively use self[:attribute]=(value) and self[:attribute] instead of write_attribute(:attribute, value) and
0591c53 @dhh Made the dynamic finders use the new find API and updated the example…
dhh authored
219 # read_attribute(:attribute) as a shorter form.
220 #
e4d845e Document automatically generated predicate methods for attributes. Cl…
Marcel Molina authored
221 # == Attribute query methods
222 #
223 # In addition to the basic accessors, query methods are also automatically available on the Active Record object.
224 # Query methods allow you to test whether an attribute value is present.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
225 #
e4d845e Document automatically generated predicate methods for attributes. Cl…
Marcel Molina authored
226 # For example, an Active Record User with the <tt>name</tt> attribute has a <tt>name?</tt> method that you can call
227 # to determine whether the user has a name:
228 #
229 # user = User.new(:name => "David")
230 # user.name? # => true
231 #
232 # anonymous = User.new(:name => "")
233 # anonymous.name? # => false
234 #
2948910 Misc doc fixes (typos/grammar/etc.). Closes #2430.
Marcel Molina authored
235 # == Accessing attributes before they have been typecasted
4eab375 @dhh Finished polishing API docs
dhh authored
236 #
2948910 Misc doc fixes (typos/grammar/etc.). Closes #2430.
Marcel Molina authored
237 # 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
238 # That can be done by using the <tt><attribute>_before_type_cast</tt> accessors that all attributes have. For example, if your Account model
239 # has a balance 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
240 #
241 # 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
242 # 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
243 # want.
244 #
ac8fd7d @dhh Added dynamic attribute-based finders as a cleaner way of getting obj…
dhh authored
245 # == Dynamic attribute-based finders
246 #
a5a82d9 @dhh Added extension capabilities to has_many and has_and_belongs_to_many …
dhh authored
247 # Dynamic attribute-based finders are a cleaner way of getting (and/or creating) objects by simple queries without turning to SQL. They work by
302c23d @dhh Fixed Base#find to honor the documentation on how :joins work and mak…
dhh authored
248 # appending the name of an attribute to <tt>find_by_</tt> or <tt>find_all_by_</tt>, so you get finders like Person.find_by_user_name,
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
249 # Person.find_all_by_last_name, Payment.find_by_transaction_id. So instead of writing
a7e6e00 Documentation for find incorrectly omits the :conditions option from …
Marcel Molina authored
250 # <tt>Person.find(:first, :conditions => ["user_name = ?", user_name])</tt>, you just do <tt>Person.find_by_user_name(user_name)</tt>.
251 # 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
252 #
ac8fd7d @dhh Added dynamic attribute-based finders as a cleaner way of getting obj…
dhh authored
253 # It's also possible to use multiple attributes in the same find by separating them with "_and_", so you get finders like
254 # <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 …
Marcel Molina authored
255 # <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 obj…
dhh authored
256 # <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
257 #
0591c53 @dhh Made the dynamic finders use the new find API and updated the example…
dhh authored
258 # It's even possible to use all the additional parameters to find. For example, the full interface for Payment.find_all_by_amount
259 # is actually Payment.find_all_by_amount(amount, options). And the full interface to Person.find_by_user_name is
64092de @fxn Improve documentation coverage and markup
fxn authored
260 # 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>.
959f362 @dhh Added find_all style to the new dynamic finders
dhh authored
261 #
a5a82d9 @dhh Added extension capabilities to has_many and has_and_belongs_to_many …
dhh authored
262 # 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
263 # <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 …
dhh authored
264 #
265 # # No 'Summer' tag exists
266 # Tag.find_or_create_by_name("Summer") # equal to Tag.create(:name => "Summer")
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
267 #
a5a82d9 @dhh Added extension capabilities to has_many and has_and_belongs_to_many …
dhh authored
268 # # Now the 'Summer' tag does exist
269 # Tag.find_or_create_by_name("Summer") # equal to Tag.find_by_name("Summer")
270 #
c10b225 @dhh Fixed that ActiveRecord#Base.find_or_create/initialize would not hono…
dhh authored
271 # # Now 'Bob' exist and is an 'admin'
272 # User.find_or_create_by_name('Bob', :age => 40) { |u| u.admin = true }
273 #
274 # 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 setted 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 bu…
sstephenson authored
275 #
276 # # No 'Winter' tag exists
277 # winter = Tag.find_or_initialize_by_name("Winter")
85fbb22 @dhh Backed out of new_record? to new? transformation as it would screw up…
dhh authored
278 # winter.new_record? # true
d19e464 @sstephenson Added find_or_initialize_by_X which works like find_or_create_by_X bu…
sstephenson authored
279 #
14cc8d2 @jeremy find_or_create_by_* takes a hash so you can create with more attribut…
jeremy authored
280 # To find by a subset of the attributes to be used for instantiating a new object, pass a hash instead of
281 # a list of parameters. For example:
282 #
283 # Tag.find_or_create_by_name(:name => "rails", :creator => current_user)
284 #
285 # That will either find an existing tag named "rails", or create a new one while setting the user that created it.
286 #
098fa94 @dhh Fixed documentation snafus #575, #576, #577, #585
dhh authored
287 # == 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
288 #
289 # 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
290 # 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
291 #
db045db @dhh Initial
dhh authored
292 # class User < ActiveRecord::Base
293 # serialize :preferences
294 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
295 #
ca2eb16 Fix syntax error in documentation. Closes #4679. [mislav@nippur.irb.hr]
Marcel Molina authored
296 # user = User.create(:preferences => { "background" => "black", "display" => large })
db045db @dhh Initial
dhh authored
297 # User.find(user.id).preferences # => { "background" => "black", "display" => large }
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
298 #
2948910 Misc doc fixes (typos/grammar/etc.). Closes #2430.
Marcel Molina authored
299 # You can also specify a class option as the second parameter that'll raise an exception if a serialized object is retrieved as a
db045db @dhh Initial
dhh authored
300 # descendent of a class not in the hierarchy. Example:
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
301 #
db045db @dhh Initial
dhh authored
302 # class User < ActiveRecord::Base
66f44e6 @dhh Updated documentation for serialize
dhh authored
303 # serialize :preferences, Hash
db045db @dhh Initial
dhh authored
304 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
305 #
0591c53 @dhh Made the dynamic finders use the new find API and updated the example…
dhh authored
306 # user = User.create(:preferences => %w( one two three ))
db045db @dhh Initial
dhh authored
307 # User.find(user.id).preferences # raises SerializationTypeMismatch
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
308 #
db045db @dhh Initial
dhh authored
309 # == Single table inheritance
310 #
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobS…
Marcel Molina authored
311 # 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
312 # by overwriting <tt>Base.inheritance_column</tt>). This means that an inheritance looking like this:
313 #
314 # class Company < ActiveRecord::Base; end
315 # class Firm < Company; end
316 # class Client < Company; end
317 # class PriorityClient < Client; end
318 #
0591c53 @dhh Made the dynamic finders use the new find API and updated the example…
dhh authored
319 # When you do Firm.create(:name => "37signals"), this record will be saved in the companies table with type = "Firm". You can then
320 # fetch this row again using Company.find(:first, "name = '37signals'") and it will return a Firm object.
db045db @dhh Initial
dhh authored
321 #
f033833 @dhh Improving documentation...
dhh authored
322 # 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
323 # like normal subclasses with no special magic for differentiating between them or reloading the right type with find.
324 #
db045db @dhh Initial
dhh authored
325 # Note, all the attributes for all the cases are kept in the same table. Read more:
326 # http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
327 #
db045db @dhh Initial
dhh authored
328 # == Connection to multiple databases in different models
329 #
330 # 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
331 # All classes inheriting from ActiveRecord::Base will use this connection. But you can also set a class-specific connection.
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobS…
Marcel Molina authored
332 # For example, if Course is an ActiveRecord::Base, but resides in a different database, you can just say Course.establish_connection
db045db @dhh Initial
dhh authored
333 # and Course *and all its subclasses* will use this connection instead.
334 #
335 # This feature is implemented by keeping a connection pool in ActiveRecord::Base that is a Hash indexed by the class. If a connection is
336 # requested, the retrieve_connection method will go up the class-hierarchy until a connection is found in the connection pool.
337 #
338 # == Exceptions
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
339 #
dc4eec1 @lifo Merge docrails:
lifo authored
340 # * ActiveRecordError - Generic error class and superclass of all other errors raised by Active Record.
341 # * AdapterNotSpecified - The configuration hash used in <tt>establish_connection</tt> didn't include an
db045db @dhh Initial
dhh authored
342 # <tt>:adapter</tt> key.
dc4eec1 @lifo Merge docrails:
lifo authored
343 # * 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
344 # (or a bad spelling of an existing one).
dc4eec1 @lifo Merge docrails:
lifo authored
345 # * AssociationTypeMismatch - The object assigned to the association wasn't of the type specified in the association definition.
346 # * SerializationTypeMismatch - The serialized object wasn't of the class specified as the second parameter.
347 # * ConnectionNotEstablished+ - No connection has been established. Use <tt>establish_connection</tt> before querying.
348 # * RecordNotFound - No record responded to the +find+ method. Either the row with the given ID doesn't exist
349 # or the row didn't meet the additional restrictions. Some +find+ calls do not raise this exception to signal
350 # nothing was found, please check its documentation for further details.
351 # * StatementInvalid - The database server rejected the SQL statement. The precise error is added in the message.
352 # * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the
353 # <tt>attributes=</tt> method. The +errors+ property of this exception contains an array of AttributeAssignmentError
d2fefbe @dhh Added MultiparameterAssignmentErrors and AttributeAssignmentError exc…
dhh authored
354 # objects that should be inspected to determine which attributes triggered the errors.
dc4eec1 @lifo Merge docrails:
lifo authored
355 # * AttributeAssignmentError - An error occurred while doing a mass assignment through the <tt>attributes=</tt> method.
d2fefbe @dhh Added MultiparameterAssignmentErrors and AttributeAssignmentError exc…
dhh authored
356 # 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 …
dhh authored
357 #
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
358 # *Note*: The attributes listed are class-level attributes (accessible from both the class and instance level).
dc4eec1 @lifo Merge docrails:
lifo authored
359 # 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
360 # instances in the current object space.
361 class Base
362 # Accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then passed
363 # 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 #7…
technoweenie authored
364 cattr_accessor :logger, :instance_writer => false
e694114 @jeremy Deprecation: removed Reloadable.
jeremy authored
365
db045db @dhh Initial
dhh authored
366 def self.inherited(child) #:nodoc:
367 @@subclasses[self] ||= []
368 @@subclasses[self] << child
369 super
370 end
e694114 @jeremy Deprecation: removed Reloadable.
jeremy authored
371
fed7d33 @dhh Fixed documentation
dhh authored
372 def self.reset_subclasses #:nodoc:
bfbf6bb @jamis Allow ARStore::Session to indicate that it should not be reloaded in …
jamis authored
373 nonreloadables = []
e7f61ea @jamis squash the memleak in dev mode finally (fingers crossed, here)
jamis authored
374 subclasses.each do |klass|
74165eb @seckar New dependencies implementation
seckar authored
375 unless Dependencies.autoloaded? klass
bfbf6bb @jamis Allow ARStore::Session to indicate that it should not be reloaded in …
jamis authored
376 nonreloadables << klass
377 next
378 end
e7f61ea @jamis squash the memleak in dev mode finally (fingers crossed, here)
jamis authored
379 klass.instance_variables.each { |var| klass.send(:remove_instance_variable, var) }
380 klass.instance_methods(false).each { |m| klass.send :undef_method, m }
381 end
bfbf6bb @jamis Allow ARStore::Session to indicate that it should not be reloaded in …
jamis authored
382 @@subclasses = {}
383 nonreloadables.each { |klass| (@@subclasses[klass.superclass] ||= []) << klass }
3c0129a @dhh Fixed memory leak with Active Record classes when Dependencies.mechan…
dhh authored
384 end
385
db045db @dhh Initial
dhh authored
386 @@subclasses = {}
c4a3634 @jeremy Corrected @@configurations typo. #1410 [david@ruppconsulting.com]
jeremy authored
387
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7…
technoweenie authored
388 cattr_accessor :configurations, :instance_writer => false
c4a3634 @jeremy Corrected @@configurations typo. #1410 [david@ruppconsulting.com]
jeremy authored
389 @@configurations = {}
390
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
391 # 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
392 # :table_name_with_underscore. If the first is specified, the Product class will look for "productid" instead of "id" as
393 # 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
394 # that this is a global setting for all Active Records.
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7…
technoweenie authored
395 cattr_accessor :primary_key_prefix_type, :instance_writer => false
db045db @dhh Initial
dhh authored
396 @@primary_key_prefix_type = nil
397
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
398 # 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
399 # 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
400 # 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 #7…
technoweenie authored
401 cattr_accessor :table_name_prefix, :instance_writer => false
db045db @dhh Initial
dhh authored
402 @@table_name_prefix = ""
403
404 # Works like +table_name_prefix+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp",
405 # "people_basecamp"). By default, the suffix is the empty string.
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7…
technoweenie authored
406 cattr_accessor :table_name_suffix, :instance_writer => false
db045db @dhh Initial
dhh authored
407 @@table_name_suffix = ""
408
84a14f2 @jeremy Raise ProtectedAttributeAssignmentError in development and test envir…
jeremy authored
409 # Indicates whether table names should be the pluralized versions of the corresponding class names.
2948910 Misc doc fixes (typos/grammar/etc.). Closes #2430.
Marcel Molina authored
410 # 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
411 # 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 #7…
technoweenie authored
412 cattr_accessor :pluralize_table_names, :instance_writer => false
db045db @dhh Initial
dhh authored
413 @@pluralize_table_names = true
414
84a14f2 @jeremy Raise ProtectedAttributeAssignmentError in development and test envir…
jeremy authored
415 # 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
416 # 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 c…
dhh authored
417 # 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 #7…
technoweenie authored
418 cattr_accessor :colorize_logging, :instance_writer => false
911614d @dhh Added ActiveRecord::Base.colorize_logging to control whether to use c…
dhh authored
419 @@colorize_logging = true
420
60de8c1 @dhh Added Base.default_timezone accessor that determines whether to use T…
dhh authored
421 # Determines whether to use Time.local (using :local) or Time.utc (using :utc) when pulling dates and times from the database.
422 # This is set to :local by default.
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7…
technoweenie authored
423 cattr_accessor :default_timezone, :instance_writer => false
60de8c1 @dhh Added Base.default_timezone accessor that determines whether to use T…
dhh authored
424 @@default_timezone = :local
d8641ca @jeremy CHANGED DEFAULT: set ActiveRecord::Base.allow_concurrency to false. …
jeremy authored
425
84a14f2 @jeremy Raise ProtectedAttributeAssignmentError in development and test envir…
jeremy authored
426 # Determines whether to use a connection for each thread, or a single shared connection for all threads.
1c66ece @jeremy Note that allow_concurrency = true means you need to verify_active_co…
jeremy authored
427 # Defaults to false. If you're writing a threaded application, set to true
428 # and periodically call verify_active_connections! to clear out connections
429 # assigned to stale threads.
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7…
technoweenie authored
430 cattr_accessor :allow_concurrency, :instance_writer => false
25fb2db @jeremy Dynamically set allow_concurrency. Closes #4044.
jeremy authored
431 @@allow_concurrency = false
d8641ca @jeremy CHANGED DEFAULT: set ActiveRecord::Base.allow_concurrency to false. …
jeremy authored
432
24c3599 @sstephenson Support using different database adapters for development and test wi…
sstephenson authored
433 # Specifies the format to use when dumping the database schema with Rails'
434 # Rakefile. If :sql, the schema is dumped as (potentially database-
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
435 # specific) SQL statements. If :ruby, the schema is dumped as an
24c3599 @sstephenson Support using different database adapters for development and test wi…
sstephenson authored
436 # ActiveRecord::Schema file which can be loaded into any database that
437 # supports migrations. Use :ruby if you want to have different database
438 # adapters for, e.g., your development and test environments.
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7…
technoweenie authored
439 cattr_accessor :schema_format , :instance_writer => false
660952e @dhh CHANGED DEFAULT: ActiveRecord::Base.schema_format is now :ruby by def…
dhh authored
440 @@schema_format = :ruby
3b0e1d9 @josh Prefer string core_ext inflector methods over directly accessing Infl…
josh authored
441
bca8751 @divoxx Add ActiveRecord option to store the full class name on STI's type co…
divoxx authored
442 # Determine whether to store the full constant name including namespace when using STI
443 superclass_delegating_accessor :store_full_sti_class
444 self.store_full_sti_class = false
3b0e1d9 @josh Prefer string core_ext inflector methods over directly accessing Infl…
josh authored
445
db045db @dhh Initial
dhh authored
446 class << self # Class methods
d5a4d5a @dhh Added ActiveRecord::Base.find(:last) (closes #11338) [miloops]
dhh authored
447 # Find operates with four different retrieval approaches:
7669011 @dhh Fixes for postgresql testing #1129, #1130, #1131
dhh authored
448 #
449 # * 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]).
450 # If no record can be found for all of the listed ids, then RecordNotFound will be raised.
451 # * Find first: This will return the first record matched by the options used. These options can either be specific
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobS…
Marcel Molina authored
452 # conditions or merely an order. If no record can be matched, nil is returned.
d5a4d5a @dhh Added ActiveRecord::Base.find(:last) (closes #11338) [miloops]
dhh authored
453 # * Find last: This will return the last record matched by the options used. These options can either be specific
454 # conditions or merely an order. If no record can be matched, nil is returned.
7d01005 @dhh Fixed documentation and prepared for release of 0.12
dhh authored
455 # * Find all: This will return all the records matched by the options used. If no records are found, an empty array is returned.
7669011 @dhh Fixes for postgresql testing #1129, #1130, #1131
dhh authored
456 #
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobS…
Marcel Molina authored
457 # All approaches accept an options hash as their last parameter. The options are:
7669011 @dhh Fixes for postgresql testing #1129, #1130, #1131
dhh authored
458 #
515886a @dhh Added documentation for new Base.find API and eager association loading
dhh authored
459 # * <tt>:conditions</tt>: An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro.
460 # * <tt>:order</tt>: An SQL fragment like "created_at DESC, name".
3309268 @jeremy Add :group option, correspond to GROUP BY, to the find method and to …
jeremy authored
461 # * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause.
515886a @dhh Added documentation for new Base.find API and eager association loading
dhh authored
462 # * <tt>:limit</tt>: An integer determining the limit on the number of rows that should be returned.
39c64ff @jeremy Clarify :offset docs. Closes #3733.
jeremy authored
463 # * <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.
9661395 Remove references to nonexistent :joins documentation. Closes #10498 …
Marcel Molina authored
464 # * <tt>:joins</tt>: Either an SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id" (rarely needed)
64092de @fxn Improve documentation coverage and markup
fxn authored
465 # or named associations in the same form used for the <tt>:include</tt> option, which will perform an INNER JOIN on the associated table(s).
9661395 Remove references to nonexistent :joins documentation. Closes #10498 …
Marcel Molina authored
466 # 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
467 # Pass <tt>:readonly => false</tt> to override.
515886a @dhh Added documentation for new Base.find API and eager association loading
dhh authored
468 # * <tt>:include</tt>: Names associations that should be loaded alongside using LEFT OUTER JOINs. The symbols named refer
469 # to already defined associations. See eager loading under Associations.
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobS…
Marcel Molina authored
470 # * <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
6f05696 @dhh Added :select option to find which can specify a different value than…
dhh authored
471 # include the joined columns.
d3cf2a6 Document find's :from option. Closes #5762. [andrew@redlinesoftware.com]
Marcel Molina authored
472 # * <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
473 # of a database view).
64fcb75 @jeremy r3618@sedna: jeremy | 2005-10-14 12:06:03 -0700
jeremy authored
474 # * <tt>:readonly</tt>: Mark the returned records read-only so they cannot be saved or updated.
15aa6e0 @jeremy r4644@asus: jeremy | 2006-06-16 14:57:03 -0700
jeremy authored
475 # * <tt>:lock</tt>: An SQL fragment like "FOR UPDATE" or "LOCK IN SHARE MODE".
64092de @fxn Improve documentation coverage and markup
fxn authored
476 # <tt>:lock => true</tt> gives connection's default exclusive lock, usually "FOR UPDATE".
7669011 @dhh Fixes for postgresql testing #1129, #1130, #1131
dhh authored
477 #
515886a @dhh Added documentation for new Base.find API and eager association loading
dhh authored
478 # Examples for find by id:
db045db @dhh Initial
dhh authored
479 # Person.find(1) # returns the object for ID = 1
480 # Person.find(1, 2, 6) # returns an array for objects with IDs in (1, 2, 6)
481 # Person.find([7, 17]) # returns an array for objects with IDs in (7, 17)
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobS…
Marcel Molina authored
482 # 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
483 # Person.find(1, :conditions => "administrator = 1", :order => "created_on DESC")
484 #
1e9e198 @jeremy Note that find results may not be in the same order as the id argumen…
jeremy authored
485 # Note that returned records may not be in the same order as the ids you
64092de @fxn Improve documentation coverage and markup
fxn authored
486 # 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 argumen…
jeremy authored
487 # to ensure the results are sorted.
488 #
515886a @dhh Added documentation for new Base.find API and eager association loading
dhh authored
489 # Examples for find first:
7d01005 @dhh Fixed documentation and prepared for release of 0.12
dhh authored
490 # 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
491 # Person.find(:first, :conditions => [ "user_name = ?", user_name])
492 # Person.find(:first, :order => "created_on DESC", :offset => 5)
493 #
d5a4d5a @dhh Added ActiveRecord::Base.find(:last) (closes #11338) [miloops]
dhh authored
494 # Examples for find last:
495 # Person.find(:last) # returns the last object fetched by SELECT * FROM people
496 # Person.find(:last, :conditions => [ "user_name = ?", user_name])
497 # Person.find(:last, :order => "created_on DESC", :offset => 5)
498 #
515886a @dhh Added documentation for new Base.find API and eager association loading
dhh authored
499 # Examples for find all:
7d01005 @dhh Fixed documentation and prepared for release of 0.12
dhh authored
500 # 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
501 # Person.find(:all, :conditions => [ "category IN (?)", categories], :limit => 50)
aa4af60 @lifo Improve documentation.
lifo authored
502 # Person.find(:all, :conditions => { :friends => ["Bob", "Steve", "Fred"] }
515886a @dhh Added documentation for new Base.find API and eager association loading
dhh authored
503 # Person.find(:all, :offset => 10, :limit => 10)
504 # Person.find(:all, :include => [ :account, :friends ])
3309268 @jeremy Add :group option, correspond to GROUP BY, to the find method and to …
jeremy authored
505 # Person.find(:all, :group => "category")
15aa6e0 @jeremy r4644@asus: jeremy | 2006-06-16 14:57:03 -0700
jeremy authored
506 #
507 # Example for find with a lock. Imagine two concurrent transactions:
508 # each will read person.visits == 2, add 1 to it, and save, resulting
509 # in two saves of person.visits = 3. By locking the row, the second
510 # transaction has to wait until the first is finished; we get the
511 # expected person.visits == 4.
512 # Person.transaction do
513 # person = Person.find(1, :lock => true)
514 # person.visits += 1
515 # person.save!
516 # end
6bd672e @dhh Added that Base#find takes an optional options hash, including :condi…
dhh authored
517 def find(*args)
edd68a5 @dhh Refactored in use of extract_options! (closes #9079) [josh]
dhh authored
518 options = args.extract_options!
c9c1852 @dhh Making ActiveRecord faster [skaes]
dhh authored
519 validate_find_options(options)
520 set_readonly_option!(options)
64fcb75 @jeremy r3618@sedna: jeremy | 2005-10-14 12:06:03 -0700
jeremy authored
521
abc895b @dhh Added new Base.find API and deprecated find_all, find_first. Added pr…
dhh authored
522 case args.first
c9c1852 @dhh Making ActiveRecord faster [skaes]
dhh authored
523 when :first then find_initial(options)
d5a4d5a @dhh Added ActiveRecord::Base.find(:last) (closes #11338) [miloops]
dhh authored
524 when :last then find_last(options)
c9c1852 @dhh Making ActiveRecord faster [skaes]
dhh authored
525 when :all then find_every(options)
526 else find_from_ids(args, options)
db045db @dhh Initial
dhh authored
527 end
528 end
3b0e1d9 @josh Prefer string core_ext inflector methods over directly accessing Infl…
josh authored
529
c6f2af5 @dhh Added ActiveRecord#Base.all/first/last as aliases for find(:all/:firs…
dhh authored
530 # This is an alias for find(:first). You can pass in all the same arguments to this method as you can
531 # to find(:first)
532 def first(*args)
533 find(:first, *args)
534 end
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
535
c6f2af5 @dhh Added ActiveRecord#Base.all/first/last as aliases for find(:all/:firs…
dhh authored
536 # This is an alias for find(:last). You can pass in all the same arguments to this method as you can
537 # to find(:last)
538 def last(*args)
539 find(:last, *args)
540 end
3b0e1d9 @josh Prefer string core_ext inflector methods over directly accessing Infl…
josh authored
541
0a6980f Let Base.all use conditions etc like first/last
David Heinemeier Hansson authored
542 # This is an alias for find(:all). You can pass in all the same arguments to this method as you can
543 # to find(:all)
544 def all(*args)
545 find(:all, *args)
546 end
3b0e1d9 @josh Prefer string core_ext inflector methods over directly accessing Infl…
josh authored
547
edf32ce More complete documentation for find_by_sql. Closes #7912 [fearoffish]
Marcel Molina authored
548 #
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
549 # Executes a custom sql query against your database and returns all the results. The results will
550 # be returned as an array with columns requested encapsulated as attributes of the model you call
551 # this method from. If you call +Product.find_by_sql+ then the results will be returned in a Product
edf32ce More complete documentation for find_by_sql. Closes #7912 [fearoffish]
Marcel Molina authored
552 # object with the attributes you specified in the SQL query.
553 #
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
554 # If you call a complicated SQL query which spans multiple tables the columns specified by the
555 # 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
556 # table.
557 #
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
558 # The +sql+ parameter is a full sql query as a string. It will be called as is, there will be
559 # no database agnostic conversions performed. This should be a last resort because using, for example,
560 # MySQL specific terms will lock you to using that particular database engine or require you to
edf32ce More complete documentation for find_by_sql. Closes #7912 [fearoffish]
Marcel Molina authored
561 # change your call if you switch engines
562 #
563 # ==== Examples
564 # # A simple sql query spanning multiple tables
565 # Post.find_by_sql "SELECT p.title, c.author FROM posts p, comments c WHERE p.id = c.post_id"
566 # > [#<Post:0x36bff9c @attributes={"title"=>"Ruby Meetup", "first_name"=>"Quentin"}>, ...]
567 #
568 # # You can use the same string replacement techniques as you can with ActiveRecord#find
569 # Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]
570 # > [#<Post:0x36bff9c @attributes={"first_name"=>"The Cheap Man Buys Twice"}>, ...]
db045db @dhh Initial
dhh authored
571 def find_by_sql(sql)
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
572 connection.select_all(sanitize_sql(sql), "#{name} Load").collect! { |record| instantiate(record) }
db045db @dhh Initial
dhh authored
573 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
574
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
575 # Checks whether a record exists in the database that matches conditions given. These conditions
576 # can either be a single integer representing a primary key id to be found, or a condition to be
971ed15 Document API for exists?'s parameter and provide examples of usage. C…
Marcel Molina authored
577 # matched like using ActiveRecord#find.
578 #
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
579 # The +id_or_conditions+ parameter can be an Integer or a String if you want to search the primary key
580 # column of the table for a matching id, or if you're looking to match against a condition you can use
971ed15 Document API for exists?'s parameter and provide examples of usage. C…
Marcel Molina authored
581 # an Array or a Hash.
582 #
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
583 # Possible gotcha: You can't pass in a condition as a string e.g. "name = 'Jamie'", this would be
971ed15 Document API for exists?'s parameter and provide examples of usage. C…
Marcel Molina authored
584 # sanitized and then queried against the primary key column as "id = 'name = \'Jamie"
585 #
586 # ==== Examples
abc895b @dhh Added new Base.find API and deprecated find_all, find_first. Added pr…
dhh authored
587 # Person.exists?(5)
58ebf30 @jeremy The exists? class method should treat a string argument as an id rath…
jeremy authored
588 # Person.exists?('5')
8085cbf @dhh Added support for conditions on Base.exists? (closes #5689) [josh@jos…
dhh authored
589 # Person.exists?(:name => "David")
58ebf30 @jeremy The exists? class method should treat a string argument as an id rath…
jeremy authored
590 # Person.exists?(['name LIKE ?', "%#{query}%"])
591 def exists?(id_or_conditions)
0ad24df @technoweenie Optimize ActiveRecord::Base#exists? to use #select_all instead of #fi…
technoweenie authored
592 connection.select_all(
593 construct_finder_sql(
3b0e1d9 @josh Prefer string core_ext inflector methods over directly accessing Infl…
josh authored
594 :select => "#{quoted_table_name}.#{primary_key}",
595 :conditions => expand_id_conditions(id_or_conditions),
0ad24df @technoweenie Optimize ActiveRecord::Base#exists? to use #select_all instead of #fi…
technoweenie authored
596 :limit => 1
3b0e1d9 @josh Prefer string core_ext inflector methods over directly accessing Infl…
josh authored
597 ),
0ad24df @technoweenie Optimize ActiveRecord::Base#exists? to use #select_all instead of #fi…
technoweenie authored
598 "#{name} Exists"
599 ).size > 0
db045db @dhh Initial
dhh authored
600 end
abc895b @dhh Added new Base.find API and deprecated find_all, find_first. Added pr…
dhh authored
601
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
602 # 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. …
Marcel Molina authored
603 # The resulting object is returned whether the object was saved successfully to the database or not.
604 #
605 # The +attributes+ parameter can be either be a Hash or an Array of Hashes. These Hashes describe the
606 # attributes on the objects that are to be created.
607 #
608 # ==== Examples
609 # # Create a single new object
610 # User.create(:first_name => 'Jamie')
dd120ed @dhh Added block-setting of attributes for Base.create like Base.new alrea…
dhh authored
611 #
a23bea7 Document API for create's attributes parameter and provide examples. …
Marcel Molina authored
612 # # Create an Array of new objects
dc4eec1 @lifo Merge docrails:
lifo authored
613 # User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }])
dd120ed @dhh Added block-setting of attributes for Base.create like Base.new alrea…
dhh authored
614 #
615 # # Create a single object and pass it into a block to set other attributes.
616 # User.create(:first_name => 'Jamie') do |u|
617 # u.is_admin = false
618 # end
619 #
620 # # Creating an Array of new objects using a block, where the block is executed for each object:
dc4eec1 @lifo Merge docrails:
lifo authored
621 # User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }]) do |u|
dd120ed @dhh Added block-setting of attributes for Base.create like Base.new alrea…
dhh authored
622 # u.is_admin = false
3b0e1d9 @josh Prefer string core_ext inflector methods over directly accessing Infl…
josh authored
623 # end
dd120ed @dhh Added block-setting of attributes for Base.create like Base.new alrea…
dhh authored
624 def create(attributes = nil, &block)
efa81da @dhh Added the option of supplying an array of ids and attributes to Base#…
dhh authored
625 if attributes.is_a?(Array)
dd120ed @dhh Added block-setting of attributes for Base.create like Base.new alrea…
dhh authored
626 attributes.collect { |attr| create(attr, &block) }
efa81da @dhh Added the option of supplying an array of ids and attributes to Base#…
dhh authored
627 else
628 object = new(attributes)
dd120ed @dhh Added block-setting of attributes for Base.create like Base.new alrea…
dhh authored
629 yield(object) if block_given?
efa81da @dhh Added the option of supplying an array of ids and attributes to Base#…
dhh authored
630 object.save
631 object
632 end
db045db @dhh Initial
dhh authored
633 end
634
1b7a18d Document options and add examples for update. Closes #7985 [fearoffish]
Marcel Molina authored
635 # Updates an object (or multiple objects) and saves it to the database, if validations pass.
636 # 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
637 #
dc4eec1 @lifo Merge docrails:
lifo authored
638 # ==== Attributes
5e99422 @dhh Updated docs (closes #3799) [ruby@bobsilva.com]
dhh authored
639 #
dc4eec1 @lifo Merge docrails:
lifo authored
640 # * +id+ - This should be the id or an array of ids to be updated.
641 # * +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
642 #
643 # ==== Examples
644 #
645 # # Updating one record:
dc4eec1 @lifo Merge docrails:
lifo authored
646 # Person.update(15, { :user_name => 'Samuel', :group => 'expert' })
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
647 #
1b7a18d Document options and add examples for update. Closes #7985 [fearoffish]
Marcel Molina authored
648 # # Updating multiple records:
dc4eec1 @lifo Merge docrails:
lifo authored
649 # people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
5e99422 @dhh Updated docs (closes #3799) [ruby@bobsilva.com]
dhh authored
650 # Person.update(people.keys, people.values)
db045db @dhh Initial
dhh authored
651 def update(id, attributes)
efa81da @dhh Added the option of supplying an array of ids and attributes to Base#…
dhh authored
652 if id.is_a?(Array)
653 idx = -1
8b5f4e4 @jeremy Ruby 1.9 compat: fix warnings, shadowed block vars, and unitialized i…
jeremy authored
654 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#…
dhh authored
655 else
656 object = find(id)
657 object.update_attributes(attributes)
658 object
659 end
db045db @dhh Initial
dhh authored
660 end
661
6a45e01 Document options and add examples for delete. Closes #7986 [fearoffish]
Marcel Molina authored
662 # Delete an object (or multiple objects) where the +id+ given matches the primary_key. A SQL +DELETE+ command
663 # is executed on the database which means that no callbacks are fired off running this. This is an efficient method
664 # of deleting records that don't need cleaning up after or other actions to be taken.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
665 #
6a45e01 Document options and add examples for delete. Closes #7986 [fearoffish]
Marcel Molina authored
666 # Objects are _not_ instantiated with this method.
667 #
dc4eec1 @lifo Merge docrails:
lifo authored
668 # ==== Attributes
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
669 #
dc4eec1 @lifo Merge docrails:
lifo authored
670 # * +id+ - Can be either an Integer or an Array of Integers.
6a45e01 Document options and add examples for delete. Closes #7986 [fearoffish]
Marcel Molina authored
671 #
672 # ==== Examples
673 #
674 # # Delete a single object
675 # Todo.delete(1)
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
676 #
6a45e01 Document options and add examples for delete. Closes #7986 [fearoffish]
Marcel Molina authored
677 # # Delete multiple objects
678 # todos = [1,2,3]
679 # Todo.delete(todos)
648b8fd @dhh Added Base.destroy and Base.delete to remove records without holding …
dhh authored
680 def delete(id)
98165fd @jeremy Consistently quote primary key column names. Closes #7763.
jeremy authored
681 delete_all([ "#{connection.quote_column_name(primary_key)} IN (?)", id ])
648b8fd @dhh Added Base.destroy and Base.delete to remove records without holding …
dhh authored
682 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
683
ed69b38 Document options and add examples for destroy. Closes #7988 [fearoffish]
Marcel Molina authored
684 # Destroy an object (or multiple objects) that has the given id, the object is instantiated first,
685 # therefore all callbacks and filters are fired off before the object is deleted. This method is
686 # 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
687 #
688 # 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
689 # from the attributes, and then calls destroy on it.
690 #
dc4eec1 @lifo Merge docrails:
lifo authored
691 # ==== Attributes
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
692 #
dc4eec1 @lifo Merge docrails:
lifo authored
693 # * +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
694 #
695 # ==== Examples
696 #
697 # # Destroy a single object
698 # Todo.destroy(1)
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
699 #
ed69b38 Document options and add examples for destroy. Closes #7988 [fearoffish]
Marcel Molina authored
700 # # Destroy multiple objects
701 # todos = [1,2,3]
702 # Todo.destroy(todos)
648b8fd @dhh Added Base.destroy and Base.delete to remove records without holding …
dhh authored
703 def destroy(id)
8b5f4e4 @jeremy Ruby 1.9 compat: fix warnings, shadowed block vars, and unitialized i…
jeremy authored
704 if id.is_a?(Array)
705 id.map { |one_id| destroy(one_id) }
706 else
707 find(id).destroy
708 end
648b8fd @dhh Added Base.destroy and Base.delete to remove records without holding …
dhh authored
709 end
710
4f1d353 Document options and add examples for update_all. Closes #7990 [fearo…
Marcel Molina authored
711 # Updates all records with details given if they match a set of conditions supplied, limits and order can
712 # also be supplied.
a38f28f @jeremy Base.update_all :order and :limit options. Useful for MySQL updates t…
jeremy authored
713 #
dc4eec1 @lifo Merge docrails:
lifo authored
714 # ==== Attributes
4f1d353 Document options and add examples for update_all. Closes #7990 [fearo…
Marcel Molina authored
715 #
dc4eec1 @lifo Merge docrails:
lifo authored
716 # * +updates+ - A String of column and value pairs that will be set on any records that match conditions.
717 # * +conditions+ - An SQL fragment like "administrator = 1" or [ "user_name = ?", username ].
718 # See conditions in the intro for more info.
719 # * +options+ - Additional options are <tt>:limit</tt> and/or <tt>:order</tt>, see the examples for usage.
4f1d353 Document options and add examples for update_all. Closes #7990 [fearo…
Marcel Molina authored
720 #
721 # ==== Examples
722 #
723 # # Update all billing objects with the 3 different attributes given
724 # Billing.update_all( "category = 'authorized', approved = 1, author = 'David'" )
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
725 #
4f1d353 Document options and add examples for update_all. Closes #7990 [fearo…
Marcel Molina authored
726 # # Update records that match our conditions
727 # Billing.update_all( "author = 'David'", "title LIKE '%Rails%'" )
728 #
729 # # Update records that match our conditions but limit it to 5 ordered by date
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
730 # Billing.update_all( "author = 'David'", "title LIKE '%Rails%'",
4f1d353 Document options and add examples for update_all. Closes #7990 [fearo…
Marcel Molina authored
731 # :order => 'created_at', :limit => 5 )
a38f28f @jeremy Base.update_all :order and :limit options. Useful for MySQL updates t…
jeremy authored
732 def update_all(updates, conditions = nil, options = {})
ebe3a0d @jeremy More thoroughly quote table names. Exposes some issues with sqlite2 a…
jeremy authored
733 sql = "UPDATE #{quoted_table_name} SET #{sanitize_sql_for_assignment(updates)} "
a38f28f @jeremy Base.update_all :order and :limit options. Useful for MySQL updates t…
jeremy authored
734 scope = scope(:find)
735 add_conditions!(sql, conditions, scope)
c36f811 @jeremy pdate_all ignores scoped :order and :limit, so post.comments.update_a…
jeremy authored
736 add_order!(sql, options[:order], nil)
737 add_limit!(sql, options, nil)
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
738 connection.update(sql, "#{name} Update")
db045db @dhh Initial
dhh authored
739 end
0d2db8a @dhh Added Base.update_collection that can update an array of id/attribute…
dhh authored
740
4b055a4 @jeremy Update destroy_all and delete_all documentation to better describe th…
jeremy authored
741 # Destroys the records matching +conditions+ by instantiating each record and calling the destroy method.
742 # This means at least 2*N database queries to destroy N records, so avoid destroy_all if you are deleting
743 # many records. If you want to simply delete records without worrying about dependent associations or
744 # callbacks, use the much faster +delete_all+ method instead.
745 #
dc4eec1 @lifo Merge docrails:
lifo authored
746 # ==== Attributes
4b055a4 @jeremy Update destroy_all and delete_all documentation to better describe th…
jeremy authored
747 #
dc4eec1 @lifo Merge docrails:
lifo authored
748 # * +conditions+ - Conditions are specified the same way as with +find+ method.
4b055a4 @jeremy Update destroy_all and delete_all documentation to better describe th…
jeremy authored
749 #
750 # ==== Example
751 #
db045db @dhh Initial
dhh authored
752 # Person.destroy_all "last_login < '2004-04-04'"
4b055a4 @jeremy Update destroy_all and delete_all documentation to better describe th…
jeremy authored
753 #
754 # This loads and destroys each person one by one, including its dependent associations and before_ and
755 # after_destroy callbacks.
db045db @dhh Initial
dhh authored
756 def destroy_all(conditions = nil)
3dfa56c @dhh Updated all references to the old find_first and find_all to use the …
dhh authored
757 find(:all, :conditions => conditions).each { |object| object.destroy }
db045db @dhh Initial
dhh authored
758 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
759
4b055a4 @jeremy Update destroy_all and delete_all documentation to better describe th…
jeremy authored
760 # Deletes the records matching +conditions+ without instantiating the records first, and hence not
761 # calling the destroy method and invoking callbacks. This is a single SQL query, much more efficient
762 # than destroy_all.
763 #
dc4eec1 @lifo Merge docrails:
lifo authored
764 # ==== Attributes
4b055a4 @jeremy Update destroy_all and delete_all documentation to better describe th…
jeremy authored
765 #
dc4eec1 @lifo Merge docrails:
lifo authored
766 # * +conditions+ - Conditions are specified the same way as with +find+ method.
4b055a4 @jeremy Update destroy_all and delete_all documentation to better describe th…
jeremy authored
767 #
768 # ==== Example
769 #
090bfce @jeremy Correct documentation for Base.delete_all. References #1568.
jeremy authored
770 # Post.delete_all "person_id = 5 AND (category = 'Something' OR category = 'Else')"
4b055a4 @jeremy Update destroy_all and delete_all documentation to better describe th…
jeremy authored
771 #
772 # This deletes the affected posts all at once with a single DELETE query. If you need to destroy dependent
773 # associations or call your before_ or after_destroy callbacks, use the +destroy_all+ method instead.
db045db @dhh Initial
dhh authored
774 def delete_all(conditions = nil)
9b6207c @jeremy Quote table names. Defaults to column quoting. Closes #4593.
jeremy authored
775 sql = "DELETE FROM #{quoted_table_name} "
c9c1852 @dhh Making ActiveRecord faster [skaes]
dhh authored
776 add_conditions!(sql, conditions, scope(:find))
db045db @dhh Initial
dhh authored
777 connection.delete(sql, "#{name} Delete all")
778 end
779
780 # 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
781 # 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
782 # using the ActiveRecord::Calculations class methods. Look into those before using this.
783 #
dc4eec1 @lifo Merge docrails:
lifo authored
784 # ==== Attributes
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
785 #
dc4eec1 @lifo Merge docrails:
lifo authored
786 # * +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
787 #
788 # ==== Examples
789 #
e17bf81 @jamis Fix typo in count_by_sql documentation #1969 [Alexey Verkhovsky]
jamis authored
790 # Product.count_by_sql "SELECT COUNT(*) FROM sales s, customers c WHERE s.customer_id = c.id"
db045db @dhh Initial
dhh authored
791 def count_by_sql(sql)
a775cb1 @dhh Added the option for sanitizing find_by_sql and the offset parts in r…
dhh authored
792 sql = sanitize_conditions(sql)
caaf40d @dhh Added AbstractAdapter#select_value and AbstractAdapter#select_values …
dhh authored
793 connection.select_value(sql, "#{name} Count").to_i
db045db @dhh Initial
dhh authored
794 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
795
8375237 @jamis Made increment_counter/decrement_counter play nicely with optimistic …
jamis authored
796 # A generic "counter updater" implementation, intended primarily to be
797 # used by increment_counter and decrement_counter, but which may also
798 # be useful on its own. It simply does a direct SQL update for the record
799 # with the given ID, altering the given hash of counters by the amount
800 # given by the corresponding value:
801 #
dc4eec1 @lifo Merge docrails:
lifo authored
802 # ==== Attributes
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
803 #
dc4eec1 @lifo Merge docrails:
lifo authored
804 # * +id+ - The id of the object you wish to update a counter on.
805 # * +counters+ - An Array of Hashes containing the names of the fields
806 # to update as keys and the amount to update the field by as values.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
807 #
6bd7d30 Document options for update_counters. Closes #8091 [fearoffish]
Marcel Molina authored
808 # ==== Examples
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
809 #
810 # # 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
811 # # increment the action_count by 1
8375237 @jamis Made increment_counter/decrement_counter play nicely with optimistic …
jamis authored
812 # Post.update_counters 5, :comment_count => -1, :action_count => 1
6bd7d30 Document options for update_counters. Closes #8091 [fearoffish]
Marcel Molina authored
813 # # Executes the following SQL:
8375237 @jamis Made increment_counter/decrement_counter play nicely with optimistic …
jamis authored
814 # # UPDATE posts
815 # # SET comment_count = comment_count - 1,
816 # # action_count = action_count + 1
817 # # WHERE id = 5
818 def update_counters(id, counters)
819 updates = counters.inject([]) { |list, (counter_name, increment)|
820 sign = increment < 0 ? "-" : "+"
98165fd @jeremy Consistently quote primary key column names. Closes #7763.
jeremy authored
821 list << "#{connection.quote_column_name(counter_name)} = #{connection.quote_column_name(counter_name)} #{sign} #{increment.abs}"
8375237 @jamis Made increment_counter/decrement_counter play nicely with optimistic …
jamis authored
822 }.join(", ")
98165fd @jeremy Consistently quote primary key column names. Closes #7763.
jeremy authored
823 update_all(updates, "#{connection.quote_column_name(primary_key)} = #{quote_value(id)}")
8375237 @jamis Made increment_counter/decrement_counter play nicely with optimistic …
jamis authored
824 end
825
15dc567 Also add documentation enhancements for increment_counter. Closes #80…
Marcel Molina authored
826 # Increment a number field by one, usually representing a count.
827 #
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
828 # This is used for caching aggregate values, so that they don't need to be computed every time.
829 # 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 [BobS…
Marcel Molina authored
830 # 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 #80…
Marcel Molina authored
831 #
dc4eec1 @lifo Merge docrails:
lifo authored
832 # ==== Attributes
15dc567 Also add documentation enhancements for increment_counter. Closes #80…
Marcel Molina authored
833 #
dc4eec1 @lifo Merge docrails:
lifo authored
834 # * +counter_name+ - The name of the field that should be incremented.
835 # * +id+ - The id of the object that should be incremented.
15dc567 Also add documentation enhancements for increment_counter. Closes #80…
Marcel Molina authored
836 #
837 # ==== Examples
838 #
839 # # Increment the post_count column for the record with an id of 5
840 # DiscussionBoard.increment_counter(:post_count, 5)
db045db @dhh Initial
dhh authored
841 def increment_counter(counter_name, id)
8375237 @jamis Made increment_counter/decrement_counter play nicely with optimistic …
jamis authored
842 update_counters(id, counter_name => 1)
db045db @dhh Initial
dhh authored
843 end
844
5bd3570 Enhance documentation for decrement_counter. Closes #8093. [fearoffish]
Marcel Molina authored
845 # Decrement a number field by one, usually representing a count.
846 #
847 # This works the same as increment_counter but reduces the column value by 1 instead of increasing it.
848 #
dc4eec1 @lifo Merge docrails:
lifo authored
849 # ==== Attributes
5bd3570 Enhance documentation for decrement_counter. Closes #8093. [fearoffish]
Marcel Molina authored
850 #
dc4eec1 @lifo Merge docrails:
lifo authored
851 # * +counter_name+ - The name of the field that should be decremented.
852 # * +id+ - The id of the object that should be decremented.
5bd3570 Enhance documentation for decrement_counter. Closes #8093. [fearoffish]
Marcel Molina authored
853 #
854 # ==== Examples
855 #
856 # # Decrement the post_count column for the record with an id of 5
857 # DiscussionBoard.decrement_counter(:post_count, 5)
db045db @dhh Initial
dhh authored
858 def decrement_counter(counter_name, id)
8375237 @jamis Made increment_counter/decrement_counter play nicely with optimistic …
jamis authored
859 update_counters(id, counter_name => -1)
db045db @dhh Initial
dhh authored
860 end
861
c450a36 @dhh Doc fixes
dhh authored
862
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
863 # Attributes named in this macro are protected from mass-assignment, such as <tt>new(attributes)</tt> and
db045db @dhh Initial
dhh authored
864 # <tt>attributes=(attributes)</tt>. Their assignment will simply be ignored. Instead, you can use the direct writer
2948910 Misc doc fixes (typos/grammar/etc.). Closes #2430.
Marcel Molina authored
865 # methods to do assignment. This is meant to protect sensitive attributes from being overwritten by URL/form hackers. Example:
db045db @dhh Initial
dhh authored
866 #
867 # class Customer < ActiveRecord::Base
868 # attr_protected :credit_rating
869 # end
870 #
871 # customer = Customer.new("name" => David, "credit_rating" => "Excellent")
872 # customer.credit_rating # => nil
873 # customer.attributes = { "description" => "Jolly fellow", "credit_rating" => "Superb" }
874 # customer.credit_rating # => nil
875 #
876 # customer.credit_rating = "Average"
877 # customer.credit_rating # => "Average"
d761ac4 Add docs explaining how to protect all attributes using attr_accessib…
Marcel Molina authored
878 #
879 # To start from an all-closed default and enable attributes as needed, have a look at attr_accessible.
db045db @dhh Initial
dhh authored
880 def attr_protected(*attributes)
3a3e7ef @jeremy attr_protected and _accessible use sets of strings instead of arrays …
jeremy authored
881 write_inheritable_attribute("attr_protected", Set.new(attributes.map(&:to_s)) + (protected_attributes || []))
db045db @dhh Initial
dhh authored
882 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
883
098fa94 @dhh Fixed documentation snafus #575, #576, #577, #585
dhh authored
884 # Returns an array of all the attributes that have been protected from mass-assignment.
db045db @dhh Initial
dhh authored
885 def protected_attributes # :nodoc:
886 read_inheritable_attribute("attr_protected")
887 end
888
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
889 # Similar to the attr_protected macro, this protects attributes of your model from mass-assignment,
f770b82 Enhance explanation with more examples for attr_accessible macro. Clo…
Marcel Molina authored
890 # such as <tt>new(attributes)</tt> and <tt>attributes=(attributes)</tt>
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
891 # however, it does it in the opposite way. This locks all attributes and only allows access to the
892 # attributes specified. Assignment to attributes not in this list will be ignored and need to be set
893 # using the direct writer methods instead. This is meant to protect sensitive attributes from being
894 # overwritten by URL/form hackers. If you'd rather start from an all-open default and restrict
f770b82 Enhance explanation with more examples for attr_accessible macro. Clo…
Marcel Molina authored
895 # attributes as needed, have a look at attr_protected.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
896 #
dc4eec1 @lifo Merge docrails:
lifo authored
897 # ==== Attributes
d761ac4 Add docs explaining how to protect all attributes using attr_accessib…
Marcel Molina authored
898 #
dc4eec1 @lifo Merge docrails:
lifo authored
899 # * <tt>*attributes</tt> A comma separated list of symbols that represent columns _not_ to be protected
f770b82 Enhance explanation with more examples for attr_accessible macro. Clo…
Marcel Molina authored
900 #
901 # ==== Examples
d761ac4 Add docs explaining how to protect all attributes using attr_accessib…
Marcel Molina authored
902 #
903 # class Customer < ActiveRecord::Base
f770b82 Enhance explanation with more examples for attr_accessible macro. Clo…
Marcel Molina authored
904 # attr_accessible :name, :nickname
d761ac4 Add docs explaining how to protect all attributes using attr_accessib…
Marcel Molina authored
905 # end
906 #
f770b82 Enhance explanation with more examples for attr_accessible macro. Clo…
Marcel Molina authored
907 # customer = Customer.new(:name => "David", :nickname => "Dave", :credit_rating => "Excellent")
908 # customer.credit_rating # => nil
909 # customer.attributes = { :name => "Jolly fellow", :credit_rating => "Superb" }
910 # customer.credit_rating # => nil
d761ac4 Add docs explaining how to protect all attributes using attr_accessib…
Marcel Molina authored
911 #
f770b82 Enhance explanation with more examples for attr_accessible macro. Clo…
Marcel Molina authored
912 # customer.credit_rating = "Average"
913 # customer.credit_rating # => "Average"
db045db @dhh Initial
dhh authored
914 def attr_accessible(*attributes)
3a3e7ef @jeremy attr_protected and _accessible use sets of strings instead of arrays …
jeremy authored
915 write_inheritable_attribute("attr_accessible", Set.new(attributes.map(&:to_s)) + (accessible_attributes || []))
db045db @dhh Initial
dhh authored
916 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
917
098fa94 @dhh Fixed documentation snafus #575, #576, #577, #585
dhh authored
918 # Returns an array of all the attributes that have been made accessible to mass-assignment.
db045db @dhh Initial
dhh authored
919 def accessible_attributes # :nodoc:
920 read_inheritable_attribute("attr_accessible")
921 end
922
66d05f5 @technoweenie Add attr_readonly to specify columns that are skipped during a normal…
technoweenie authored
923 # Attributes listed as readonly can be set for a new record, but will be ignored in database updates afterwards.
924 def attr_readonly(*attributes)
a33007d @jeremy attr_readonly uses a set of strings instead of an array of symbols in…
jeremy authored
925 write_inheritable_attribute("attr_readonly", Set.new(attributes.map(&:to_s)) + (readonly_attributes || []))
66d05f5 @technoweenie Add attr_readonly to specify columns that are skipped during a normal…
technoweenie authored
926 end
927
928 # Returns an array of all the attributes that have been specified as readonly.
929 def readonly_attributes
930 read_inheritable_attribute("attr_readonly")
931 end
c450a36 @dhh Doc fixes
dhh authored
932
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
933 # If you have an attribute that needs to be saved to the database as an object, and retrieved as the same object,
934 # then specify the name of that attribute using this method and it will be handled automatically.
935 # The serialization is done through YAML. If +class_name+ is specified, the serialized object must be of that
1a0cdf7 @dhh Docfix (closes #8096)
dhh authored
936 # class on retrieval or +SerializationTypeMismatch+ will be raised.
937 #
dc4eec1 @lifo Merge docrails:
lifo authored
938 # ==== Attributes
1a0cdf7 @dhh Docfix (closes #8096)
dhh authored
939 #
dc4eec1 @lifo Merge docrails:
lifo authored
940 # * +attr_name+ - The field name that should be serialized.
941 # * +class_name+ - Optional, class name that the object type should be equal to.
1a0cdf7 @dhh Docfix (closes #8096)
dhh authored
942 #
943 # ==== Example
944 # # Serialize a preferences attribute
945 # class User
946 # serialize :preferences
947 # end
db045db @dhh Initial
dhh authored
948 def serialize(attr_name, class_name = Object)
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
949 serialized_attributes[attr_name.to_s] = class_name
db045db @dhh Initial
dhh authored
950 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
951
db045db @dhh Initial
dhh authored
952 # Returns a hash of all the attributes that have been specified for serialization as keys and their class restriction as values.
953 def serialized_attributes
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
954 read_inheritable_attribute("attr_serialized") or write_inheritable_attribute("attr_serialized", {})
db045db @dhh Initial
dhh authored
955 end
956
c450a36 @dhh Doc fixes
dhh authored