Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 722 lines (671 sloc) 29.738 kB
59f3218 @tenderlove load and prefer psych as the YAML parser when it is available
tenderlove authored
1 begin
2 require 'psych'
3 rescue LoadError
4 end
5
db045db @dhh Initial
dhh authored
6 require 'yaml'
aabf909 @jeremy Correct reader method generation for primary key attribute: handle ca…
jeremy authored
7 require 'set'
fab664a @jonleighton Fix another race condition.
jonleighton authored
8 require 'thread'
a15e02d @josevalim Unify benchmark APIs.
josevalim authored
9 require 'active_support/benchmarkable'
f5d720f @jeremy Opt in to Dependencies
jeremy authored
10 require 'active_support/dependencies'
033e0a0 @josevalim ActiveRecord and ActionPack now use the new descendants implementation.
josevalim authored
11 require 'active_support/descendants_tracker'
5f222c5 @jeremy Remove 'core' fluff. Hookable ActiveSupport.load_all!
jeremy authored
12 require 'active_support/time'
bab1f91 @phs table_name_prefix and table_name_suffix are class_attributes instead …
phs authored
13 require 'active_support/core_ext/class/attribute'
e8550ee @jeremy Cherry-pick core extensions
jeremy authored
14 require 'active_support/core_ext/class/attribute_accessors'
15 require 'active_support/core_ext/class/delegating_attributes'
d7db6a8 @joshk class inheritable attributes is used no more! all internal use of cla…
joshk authored
16 require 'active_support/core_ext/class/attribute'
e8550ee @jeremy Cherry-pick core extensions
jeremy authored
17 require 'active_support/core_ext/array/extract_options'
18 require 'active_support/core_ext/hash/deep_merge'
19 require 'active_support/core_ext/hash/indifferent_access'
20 require 'active_support/core_ext/hash/slice'
21 require 'active_support/core_ext/string/behavior'
89978f1 @fxn moves Object#singleton_class to Kernel#singleton_class to match Ruby …
fxn authored
22 require 'active_support/core_ext/kernel/singleton_class'
a7fd564 @lifo Add Model.select/group/order/limit/joins/conditions/preload/eager_loa…
lifo authored
23 require 'active_support/core_ext/module/delegation'
4a8c880 @fxn refactors AR::Base#reset_table_name
fxn authored
24 require 'active_support/core_ext/module/introspection'
105f9b8 @fxn adds missing requires for Object#duplicable?
fxn authored
25 require 'active_support/core_ext/object/duplicable'
76f024a @fxn adds missing requires for Object#blank? and Object#present?
fxn authored
26 require 'active_support/core_ext/object/blank'
0b72a04 @jonleighton Deprecate set_table_name in favour of self.table_name= or defining yo…
jonleighton authored
27 require 'active_support/deprecation'
39d6f9e @wycats Make many parts of Rails lazy. In order to facilitate this,
wycats authored
28 require 'arel'
29 require 'active_record/errors'
6788db8 @josevalim Move Rails::LogSubscriber to ActiveSupport::LogSubscriber, allowing f…
josevalim authored
30 require 'active_record/log_subscriber'
cfeac38 @fxn implements a much faster auto EXPLAIN, closes #3843 [José Valim & Xav…
fxn authored
31 require 'active_record/explain_subscriber'
db045db @dhh Initial
dhh authored
32
33 module ActiveRecord #:nodoc:
606088d @eac Mass assignment security refactoring
eac authored
34 # = Active Record
4ad6103 @rizwanreza Adds title and basic description where needed.
rizwanreza authored
35 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
36 # Active Record objects don't specify their attributes directly, but rather infer them from
37 # the table definition with which they're linked. Adding, removing, and changing attributes
38 # and their type is done directly in the database. Any change is instantly reflected in the
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
39 # 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
40 # database table will happen automatically in most common cases, but can be overwritten for the uncommon ones.
41 #
20333be @tilsammans fix broken relative links [#5415 state:committed]
tilsammans authored
42 # See the mapping rules in table_name and the full example in link:files/activerecord/README_rdoc.html for more insight.
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
43 #
db045db @dhh Initial
dhh authored
44 # == Creation
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
45 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
46 # Active Records accept constructor parameters either in a hash or as a block. The hash
47 # method is especially useful when you're receiving the data from somewhere else, like an
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
48 # HTTP request. It works like this:
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
49 #
0591c53 @dhh Made the dynamic finders use the new find API and updated the example…
dhh authored
50 # user = User.new(:name => "David", :occupation => "Code Artist")
db045db @dhh Initial
dhh authored
51 # user.name # => "David"
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
52 #
db045db @dhh Initial
dhh authored
53 # You can also use block initialization:
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
54 #
db045db @dhh Initial
dhh authored
55 # user = User.new do |u|
56 # u.name = "David"
57 # u.occupation = "Code Artist"
58 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
59 #
db045db @dhh Initial
dhh authored
60 # 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
61 #
db045db @dhh Initial
dhh authored
62 # user = User.new
63 # user.name = "David"
64 # user.occupation = "Code Artist"
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
65 #
db045db @dhh Initial
dhh authored
66 # == Conditions
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
67 #
c5ec16e @dhh Added simple hash conditions to find that'll just convert hash to an …
dhh authored
68 # Conditions can either be specified as a string, array, or hash representing the WHERE-part of an SQL statement.
9e18380 @fxn Revert "Explicitly included hashes in sentence regarding SQL-injectio…
fxn authored
69 # The array form is to be used when the condition input is tainted and requires sanitization. The string form can
70 # be used for statements that don't involve tainted data. The hash form works much like the array form, except
71 # only equality and range is possible. Examples:
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
72 #
48052d7 @jeremy to_xml fixes, features, and speedup. Closes #4989.
jeremy authored
73 # class User < ActiveRecord::Base
db045db @dhh Initial
dhh authored
74 # def self.authenticate_unsafely(user_name, password)
2c27e3d @lifo Some doc updates reflecting the new query API
lifo authored
75 # where("user_name = '#{user_name}' AND password = '#{password}'").first
db045db @dhh Initial
dhh authored
76 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
77 #
db045db @dhh Initial
dhh authored
78 # def self.authenticate_safely(user_name, password)
2c27e3d @lifo Some doc updates reflecting the new query API
lifo authored
79 # where("user_name = ? AND password = ?", user_name, password).first
db045db @dhh Initial
dhh authored
80 # end
c5ec16e @dhh Added simple hash conditions to find that'll just convert hash to an …
dhh authored
81 #
82 # def self.authenticate_safely_simply(user_name, password)
2c27e3d @lifo Some doc updates reflecting the new query API
lifo authored
83 # where(:user_name => user_name, :password => password).first
c5ec16e @dhh Added simple hash conditions to find that'll just convert hash to an …
dhh authored
84 # end
db045db @dhh Initial
dhh authored
85 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
86 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
87 # The <tt>authenticate_unsafely</tt> method inserts the parameters directly into the query
88 # and is thus susceptible to SQL-injection attacks if the <tt>user_name</tt> and +password+
04d37b0 @smartinez87 Remove extra whitespaces
smartinez87 authored
89 # parameters come directly from an HTTP request. The <tt>authenticate_safely</tt> and
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
90 # <tt>authenticate_safely_simply</tt> both will sanitize the <tt>user_name</tt> and +password+
91 # before inserting them in the query, which will ensure that an attacker can't escape the
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
92 # query and fake the login (or worse).
2575b3b @dhh Added extra words of caution for guarding against SQL-injection attacks
dhh authored
93 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
94 # When using multiple parameters in the conditions, it can easily become hard to read exactly
95 # what the fourth or fifth question mark is supposed to represent. In those cases, you can
96 # resort to named bind variables instead. That's done by replacing the question marks with
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
97 # symbols and supplying a hash with values for the matching symbol keys:
5cd38ca @dhh Added documentation about named bind variables
dhh authored
98 #
2c27e3d @lifo Some doc updates reflecting the new query API
lifo authored
99 # Company.where(
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
100 # "id = :id AND name = :name AND division = :division AND created_at > :accounting_date",
5cd38ca @dhh Added documentation about named bind variables
dhh authored
101 # { :id => 3, :name => "37signals", :division => "First", :accounting_date => '2005-01-01' }
2c27e3d @lifo Some doc updates reflecting the new query API
lifo authored
102 # ).first
5cd38ca @dhh Added documentation about named bind variables
dhh authored
103 #
c5ec16e @dhh Added simple hash conditions to find that'll just convert hash to an …
dhh authored
104 # Similarly, a simple hash without a statement will generate conditions based on equality with the SQL AND
105 # operator. For instance:
106 #
2c27e3d @lifo Some doc updates reflecting the new query API
lifo authored
107 # Student.where(:first_name => "Harvey", :status => 1)
108 # Student.where(params[:student])
c5ec16e @dhh Added simple hash conditions to find that'll just convert hash to an …
dhh authored
109 #
2876707 @jeremy Pass a range in :conditions to use the SQL BETWEEN operator. Closes #…
jeremy authored
110 # A range may be used in the hash to use the SQL BETWEEN operator:
111 #
2c27e3d @lifo Some doc updates reflecting the new query API
lifo authored
112 # Student.where(:grade => 9..12)
c5ec16e @dhh Added simple hash conditions to find that'll just convert hash to an …
dhh authored
113 #
aa4af60 @lifo Improve documentation.
lifo authored
114 # An array may be used in the hash to use the SQL IN operator:
115 #
2c27e3d @lifo Some doc updates reflecting the new query API
lifo authored
116 # Student.where(:grade => [9,11,12])
aa4af60 @lifo Improve documentation.
lifo authored
117 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
118 # When joining tables, nested hashes or keys written in the form 'table_name.column_name'
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
119 # can be used to qualify the table name of a particular condition. For instance:
e033b5d @lifo Merge docrails
lifo authored
120 #
e552fe1 change activerecord query conditions example to avoid 'type' as colum…
Steve Bourne authored
121 # Student.joins(:schools).where(:schools => { :category => 'public' })
122 # Student.joins(:schools).where('schools.category' => 'public' )
e033b5d @lifo Merge docrails
lifo authored
123 #
db045db @dhh Initial
dhh authored
124 # == Overwriting default accessors
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
125 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
126 # All column values are automatically available through basic accessors on the Active Record
127 # object, but sometimes you want to specialize this behavior. This can be done by overwriting
128 # the default accessors (using the same name as the attribute) and calling
129 # <tt>read_attribute(attr_name)</tt> and <tt>write_attribute(attr_name, value)</tt> to actually
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
130 # change things.
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
131 #
db045db @dhh Initial
dhh authored
132 # class Song < ActiveRecord::Base
133 # # 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
134 #
db045db @dhh Initial
dhh authored
135 # def length=(minutes)
64092de @fxn Improve documentation coverage and markup
fxn authored
136 # write_attribute(:length, minutes.to_i * 60)
db045db @dhh Initial
dhh authored
137 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
138 #
db045db @dhh Initial
dhh authored
139 # def length
0591c53 @dhh Made the dynamic finders use the new find API and updated the example…
dhh authored
140 # read_attribute(:length) / 60
db045db @dhh Initial
dhh authored
141 # end
142 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
143 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
144 # You can alternatively use <tt>self[:attribute]=(value)</tt> and <tt>self[:attribute]</tt>
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
145 # instead of <tt>write_attribute(:attribute, value)</tt> and <tt>read_attribute(:attribute)</tt>.
0591c53 @dhh Made the dynamic finders use the new find API and updated the example…
dhh authored
146 #
e4d845e Document automatically generated predicate methods for attributes. Cl…
Marcel Molina authored
147 # == Attribute query methods
148 #
149 # In addition to the basic accessors, query methods are also automatically available on the Active Record object.
150 # Query methods allow you to test whether an attribute value is present.
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
151 #
e4d845e Document automatically generated predicate methods for attributes. Cl…
Marcel Molina authored
152 # For example, an Active Record User with the <tt>name</tt> attribute has a <tt>name?</tt> method that you can call
153 # to determine whether the user has a name:
154 #
155 # user = User.new(:name => "David")
156 # user.name? # => true
157 #
158 # anonymous = User.new(:name => "")
159 # anonymous.name? # => false
160 #
2948910 Misc doc fixes (typos/grammar/etc.). Closes #2430.
Marcel Molina authored
161 # == Accessing attributes before they have been typecasted
4eab375 @dhh Finished polishing API docs
dhh authored
162 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
163 # Sometimes you want to be able to read the raw attribute data without having the column-determined
164 # typecast run its course first. That can be done by using the <tt><attribute>_before_type_cast</tt>
165 # accessors that all attributes have. For example, if your Account model has a <tt>balance</tt> attribute,
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
166 # 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
167 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
168 # This is especially useful in validation situations where the user might supply a string for an
169 # integer field and you want to display the original string back in an error message. Accessing the
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
170 # attribute normally would typecast the string to 0, which isn't what you want.
4eab375 @dhh Finished polishing API docs
dhh authored
171 #
ac8fd7d @dhh Added dynamic attribute-based finders as a cleaner way of getting obj…
dhh authored
172 # == Dynamic attribute-based finders
173 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
174 # Dynamic attribute-based finders are a cleaner way of getting (and/or creating) objects
175 # by simple queries without turning to SQL. They work by appending the name of an attribute
176 # to <tt>find_by_</tt>, <tt>find_last_by_</tt>, or <tt>find_all_by_</tt> and thus produces finders
177 # like <tt>Person.find_by_user_name</tt>, <tt>Person.find_all_by_last_name</tt>, and
178 # <tt>Payment.find_by_transaction_id</tt>. Instead of writing
2c27e3d @lifo Some doc updates reflecting the new query API
lifo authored
179 # <tt>Person.where(:user_name => user_name).first</tt>, you just do <tt>Person.find_by_user_name(user_name)</tt>.
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
180 # And instead of writing <tt>Person.where(:last_name => last_name).all</tt>, you just do
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
181 # <tt>Person.find_all_by_last_name(last_name)</tt>.
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
182 #
56efdbc Document exclamation point on dynamic finders
Florent Guilleux authored
183 # It's possible to add an exclamation point (!) on the end of the dynamic finders to get them to raise an
0d5a6f6 @jonleighton In 1efd88283ef68d912df215125951a87526768a51, ConnectionAdapters was p…
jonleighton authored
184 # <tt>ActiveRecord::RecordNotFound</tt> error if they do not return any records,
56efdbc Document exclamation point on dynamic finders
Florent Guilleux authored
185 # like <tt>Person.find_by_last_name!</tt>.
186 #
d3eacf9 @neerajdotname Adding to AR::Base documentation about dynamically scopeded_by query
neerajdotname authored
187 # It's also possible to use multiple attributes in the same find by separating them with "_and_".
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
188 #
d3eacf9 @neerajdotname Adding to AR::Base documentation about dynamically scopeded_by query
neerajdotname authored
189 # Person.where(:user_name => user_name, :password => password).first
2acb5e3 @fxn removes unrealistic example (authentication plus gender?), that it is…
fxn authored
190 # Person.find_by_user_name_and_password(user_name, password) # with dynamic finder
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
191 #
d3eacf9 @neerajdotname Adding to AR::Base documentation about dynamically scopeded_by query
neerajdotname authored
192 # It's even possible to call these dynamic finder methods on relations and named scopes.
2c27e3d @lifo Some doc updates reflecting the new query API
lifo authored
193 #
194 # Payment.order("created_on").find_all_by_amount(50)
195 # Payment.pending.find_last_by_amount(100)
959f362 @dhh Added find_all style to the new dynamic finders
dhh authored
196 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
197 # The same dynamic finder style can be used to create the object if it doesn't already exist.
198 # This dynamic finder is called with <tt>find_or_create_by_</tt> and will return the object if
199 # it already exists and otherwise creates it, then returns it. Protected attributes won't be set
200 # unless they are given in a block.
a5a82d9 @dhh Added extension capabilities to has_many and has_and_belongs_to_many …
dhh authored
201 #
202 # # No 'Summer' tag exists
203 # Tag.find_or_create_by_name("Summer") # equal to Tag.create(:name => "Summer")
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
204 #
a5a82d9 @dhh Added extension capabilities to has_many and has_and_belongs_to_many …
dhh authored
205 # # Now the 'Summer' tag does exist
206 # Tag.find_or_create_by_name("Summer") # equal to Tag.find_by_name("Summer")
207 #
c10b225 @dhh Fixed that ActiveRecord#Base.find_or_create/initialize would not hono…
dhh authored
208 # # Now 'Bob' exist and is an 'admin'
209 # User.find_or_create_by_name('Bob', :age => 40) { |u| u.admin = true }
210 #
a01f0ab @pixeltrix Add documentation for find_or_create_by_{attribute}! method.
pixeltrix authored
211 # Adding an exclamation point (!) on to the end of <tt>find_or_create_by_</tt> will
212 # raise an <tt>ActiveRecord::RecordInvalid</tt> error if the new record is invalid.
213 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
214 # Use the <tt>find_or_initialize_by_</tt> finder if you want to return a new record without
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
215 # saving it first. Protected attributes won't be set unless they are given in a block.
d19e464 @sstephenson Added find_or_initialize_by_X which works like find_or_create_by_X bu…
sstephenson authored
216 #
217 # # No 'Winter' tag exists
218 # winter = Tag.find_or_initialize_by_name("Winter")
1f06652 @dchelimsky use persisted? instead of new_record? wherever possible
dchelimsky authored
219 # winter.persisted? # false
d19e464 @sstephenson Added find_or_initialize_by_X which works like find_or_create_by_X bu…
sstephenson authored
220 #
14cc8d2 @jeremy find_or_create_by_* takes a hash so you can create with more attribut…
jeremy authored
221 # To find by a subset of the attributes to be used for instantiating a new object, pass a hash instead of
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
222 # a list of parameters.
14cc8d2 @jeremy find_or_create_by_* takes a hash so you can create with more attribut…
jeremy authored
223 #
224 # Tag.find_or_create_by_name(:name => "rails", :creator => current_user)
225 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
226 # That will either find an existing tag named "rails", or create a new one while setting the
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
227 # user that created it.
14cc8d2 @jeremy find_or_create_by_* takes a hash so you can create with more attribut…
jeremy authored
228 #
d3eacf9 @neerajdotname Adding to AR::Base documentation about dynamically scopeded_by query
neerajdotname authored
229 # Just like <tt>find_by_*</tt>, you can also use <tt>scoped_by_*</tt> to retrieve data. The good thing about
230 # using this feature is that the very first time result is returned using <tt>method_missing</tt> technique
231 # but after that the method is declared on the class. Henceforth <tt>method_missing</tt> will not be hit.
232 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
233 # User.scoped_by_user_name('David')
d3eacf9 @neerajdotname Adding to AR::Base documentation about dynamically scopeded_by query
neerajdotname authored
234 #
098fa94 @dhh Fixed documentation snafus #575, #576, #577, #585
dhh authored
235 # == 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
236 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
237 # Active Record can serialize any object in text columns using YAML. To do so, you must
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
238 # specify this with a call to the class method +serialize+.
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
239 # This makes it possible to store arrays, hashes, and other non-mappable objects without doing
240 # any additional work.
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
241 #
db045db @dhh Initial
dhh authored
242 # class User < ActiveRecord::Base
243 # serialize :preferences
244 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
245 #
ca2eb16 Fix syntax error in documentation. Closes #4679. [mislav@nippur.irb.hr]
Marcel Molina authored
246 # user = User.create(:preferences => { "background" => "black", "display" => large })
db045db @dhh Initial
dhh authored
247 # User.find(user.id).preferences # => { "background" => "black", "display" => large }
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
248 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
249 # You can also specify a class option as the second parameter that'll raise an exception
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
250 # if a serialized object is retrieved as a descendant of a class not in the hierarchy.
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
251 #
db045db @dhh Initial
dhh authored
252 # class User < ActiveRecord::Base
66f44e6 @dhh Updated documentation for serialize
dhh authored
253 # serialize :preferences, Hash
db045db @dhh Initial
dhh authored
254 # end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
255 #
0591c53 @dhh Made the dynamic finders use the new find API and updated the example…
dhh authored
256 # user = User.create(:preferences => %w( one two three ))
db045db @dhh Initial
dhh authored
257 # User.find(user.id).preferences # raises SerializationTypeMismatch
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
258 #
351331f @guillermo Make serialized columns with explicit object_type return a new instan…
guillermo authored
259 # When you specify a class option, the default value for that attribute will be a new
260 # instance of that class.
261 #
262 # class User < ActiveRecord::Base
263 # serialize :preferences, OpenStruct
264 # end
265 #
266 # user = User.new
267 # user.preferences.theme_color = "red"
268 #
269 #
db045db @dhh Initial
dhh authored
270 # == Single table inheritance
271 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
272 # Active Record allows inheritance by storing the name of the class in a column that by
273 # default is named "type" (can be changed by overwriting <tt>Base.inheritance_column</tt>).
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
274 # This means that an inheritance looking like this:
db045db @dhh Initial
dhh authored
275 #
276 # class Company < ActiveRecord::Base; end
277 # class Firm < Company; end
278 # class Client < Company; end
279 # class PriorityClient < Client; end
280 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
281 # When you do <tt>Firm.create(:name => "37signals")</tt>, this record will be saved in
282 # the companies table with type = "Firm". You can then fetch this row again using
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
283 # <tt>Company.where(:name => '37signals').first</tt> and it will return a Firm object.
db045db @dhh Initial
dhh authored
284 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
285 # If you don't have a type column defined in your table, single-table inheritance won't
286 # be triggered. In that case, it'll work just like normal subclasses with no special magic
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
287 # for differentiating between them or reloading the right type with find.
f033833 @dhh Improving documentation...
dhh authored
288 #
db045db @dhh Initial
dhh authored
289 # Note, all the attributes for all the cases are kept in the same table. Read more:
290 # http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
291 #
db045db @dhh Initial
dhh authored
292 # == Connection to multiple databases in different models
293 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
294 # Connections are usually created through ActiveRecord::Base.establish_connection and retrieved
295 # by ActiveRecord::Base.connection. All classes inheriting from ActiveRecord::Base will use this
296 # connection. But you can also set a class-specific connection. For example, if Course is an
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
297 # ActiveRecord::Base, but resides in a different database, you can just say <tt>Course.establish_connection</tt>
98dc582 @lifo Merge docrails.
lifo authored
298 # and Course and all of its subclasses will use this connection instead.
db045db @dhh Initial
dhh authored
299 #
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
300 # This feature is implemented by keeping a connection pool in ActiveRecord::Base that is
301 # a Hash indexed by the class. If a connection is requested, the retrieve_connection method
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
302 # will go up the class-hierarchy until a connection is found in the connection pool.
db045db @dhh Initial
dhh authored
303 #
304 # == Exceptions
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
305 #
dc4eec1 @lifo Merge docrails:
lifo authored
306 # * ActiveRecordError - Generic error class and superclass of all other errors raised by Active Record.
307 # * AdapterNotSpecified - The configuration hash used in <tt>establish_connection</tt> didn't include an
db045db @dhh Initial
dhh authored
308 # <tt>:adapter</tt> key.
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
309 # * AdapterNotFound - The <tt>:adapter</tt> key used in <tt>establish_connection</tt> specified a
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
310 # non-existent adapter
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
311 # (or a bad spelling of an existing one).
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
312 # * AssociationTypeMismatch - The object assigned to the association wasn't of the type
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
313 # specified in the association definition.
dc4eec1 @lifo Merge docrails:
lifo authored
314 # * SerializationTypeMismatch - The serialized object wasn't of the class specified as the second parameter.
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
315 # * ConnectionNotEstablished+ - No connection has been established. Use <tt>establish_connection</tt>
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
316 # before querying.
dc4eec1 @lifo Merge docrails:
lifo authored
317 # * RecordNotFound - No record responded to the +find+ method. Either the row with the given ID doesn't exist
318 # or the row didn't meet the additional restrictions. Some +find+ calls do not raise this exception to signal
319 # nothing was found, please check its documentation for further details.
320 # * StatementInvalid - The database server rejected the SQL statement. The precise error is added in the message.
321 # * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
322 # <tt>attributes=</tt> method. The +errors+ property of this exception contains an array of
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
323 # AttributeAssignmentError
d2fefbe @dhh Added MultiparameterAssignmentErrors and AttributeAssignmentError exc…
dhh authored
324 # objects that should be inspected to determine which attributes triggered the errors.
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
325 # * AttributeAssignmentError - An error occurred while doing a mass assignment through the
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
326 # <tt>attributes=</tt> method.
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
327 # You can inspect the +attribute+ property of the exception object to determine which attribute
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
328 # triggered the error.
5707027 @dhh Added better exception error when unknown column types are used with …
dhh authored
329 #
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
330 # *Note*: The attributes listed are class-level attributes (accessible from both the class and instance level).
dc4eec1 @lifo Merge docrails:
lifo authored
331 # 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
332 # instances in the current object space.
333 class Base
0905396 @miloops construct_finder_sql now use Arel
miloops authored
334 ##
dbbae5e @lifo Merge with docrails
lifo authored
335 # :singleton-method:
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
336 # Accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class,
337 # which is then passed on to any new database connections made and which can be retrieved on both
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
338 # a class and instance level by calling +logger+.
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7…
technoweenie authored
339 cattr_accessor :logger, :instance_writer => false
e694114 @jeremy Deprecation: removed Reloadable.
jeremy authored
340
dbbae5e @lifo Merge with docrails
lifo authored
341 ##
342 # :singleton-method:
a293278 @lifo Merge docrails
lifo authored
343 # Contains the database configuration - as is typically stored in config/database.yml -
344 # as a Hash.
345 #
346 # For example, the following database.yml...
0905396 @miloops construct_finder_sql now use Arel
miloops authored
347 #
a293278 @lifo Merge docrails
lifo authored
348 # development:
349 # adapter: sqlite3
350 # database: db/development.sqlite3
0905396 @miloops construct_finder_sql now use Arel
miloops authored
351 #
a293278 @lifo Merge docrails
lifo authored
352 # production:
353 # adapter: sqlite3
354 # database: db/production.sqlite3
355 #
356 # ...would result in ActiveRecord::Base.configurations to look like this:
357 #
358 # {
359 # 'development' => {
360 # 'adapter' => 'sqlite3',
361 # 'database' => 'db/development.sqlite3'
362 # },
363 # 'production' => {
364 # 'adapter' => 'sqlite3',
365 # 'database' => 'db/production.sqlite3'
366 # }
367 # }
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7…
technoweenie authored
368 cattr_accessor :configurations, :instance_writer => false
c4a3634 @jeremy Corrected @@configurations typo. #1410 [david@ruppconsulting.com]
jeremy authored
369 @@configurations = {}
370
dbbae5e @lifo Merge with docrails
lifo authored
371 ##
372 # :singleton-method:
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -ex…
spastorino authored
373 # Determines whether to use Time.local (using :local) or Time.utc (using :utc) when pulling
b8d9d9c @neerajdotname updating documentation to ensure line does not exceed 100 columns
neerajdotname authored
374 # dates and times from the database. This is set to :local by default.
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7…
technoweenie authored
375 cattr_accessor :default_timezone, :instance_writer => false
60de8c1 @dhh Added Base.default_timezone accessor that determines whether to use T…
dhh authored
376 @@default_timezone = :local
d8641ca @jeremy CHANGED DEFAULT: set ActiveRecord::Base.allow_concurrency to false. …
jeremy authored
377
dbbae5e @lifo Merge with docrails
lifo authored
378 ##
379 # :singleton-method:
24c3599 @sstephenson Support using different database adapters for development and test wi…
sstephenson authored
380 # Specifies the format to use when dumping the database schema with Rails'
04d37b0 @smartinez87 Remove extra whitespaces
smartinez87 authored
381 # Rakefile. If :sql, the schema is dumped as (potentially database-
382 # 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
383 # ActiveRecord::Schema file which can be loaded into any database that
04d37b0 @smartinez87 Remove extra whitespaces
smartinez87 authored
384 # supports migrations. Use :ruby if you want to have different database
24c3599 @sstephenson Support using different database adapters for development and test wi…
sstephenson authored
385 # adapters for, e.g., your development and test environments.
1a11bff @technoweenie Don't create instance writer methods for class attributes. Closes #7…
technoweenie authored
386 cattr_accessor :schema_format , :instance_writer => false
660952e @dhh CHANGED DEFAULT: ActiveRecord::Base.schema_format is now :ruby by def…
dhh authored
387 @@schema_format = :ruby
3b0e1d9 @josh Prefer string core_ext inflector methods over directly accessing Infl…
josh authored
388
dbbae5e @lifo Merge with docrails
lifo authored
389 ##
390 # :singleton-method:
155f0be @rizwanreza Changes migration number to version due to ambiguity. [#3065 state:co…
rizwanreza authored
391 # Specify whether or not to use timestamps for migration versions
bbab639 @nikz Set config.active_record.timestamped_migrations = false to have migra…
nikz authored
392 cattr_accessor :timestamped_migrations , :instance_writer => false
393 @@timestamped_migrations = true
394
db045db @dhh Initial
dhh authored
395 class << self # Class methods
61bcc31 @joshsusser use GeneratedFeatureMethods module for associations
joshsusser authored
396 def inherited(child_class) #:nodoc:
fab664a @jonleighton Fix another race condition.
jonleighton authored
397 child_class.initialize_generated_modules
61bcc31 @joshsusser use GeneratedFeatureMethods module for associations
joshsusser authored
398 super
399 end
400
fab664a @jonleighton Fix another race condition.
jonleighton authored
401 def initialize_generated_modules #:nodoc:
402 @attribute_methods_mutex = Mutex.new
403
404 # force attribute methods to be higher in inheritance hierarchy than other generated methods
405 generated_attribute_methods
406 generated_feature_methods
407 end
408
61bcc31 @joshsusser use GeneratedFeatureMethods module for associations
joshsusser authored
409 def generated_feature_methods
3da5fba @jonleighton Fix ruby 1.8 compat. const_defined? only takes a second arg on 1.9.
jonleighton authored
410 @generated_feature_methods ||= begin
411 mod = const_set(:GeneratedFeatureMethods, Module.new)
412 include mod
413 mod
61bcc31 @joshsusser use GeneratedFeatureMethods module for associations
joshsusser authored
414 end
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
415 end
fd40fbc @jeremy Generate less garbage when expanding range bind variables in conditions
jeremy authored
416
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
417 # Returns a string like 'Post(id:integer, title:string, body:text)'
418 def inspect
419 if self == Base
420 super
421 elsif abstract_class?
422 "#{super}(abstract)"
423 elsif table_exists?
424 attr_list = columns.map { |c| "#{c.name}: #{c.type}" } * ', '
425 "#{super}(#{attr_list})"
426 else
427 "#{super}(Table doesn't exist)"
428 end
429 end
cd994ef @lifo Allow conditions on multiple tables to be specified using hash.
lifo authored
430
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
431 # Overwrite the default class equality method to provide support for association proxies.
432 def ===(object)
433 object.is_a?(self)
434 end
fd40fbc @jeremy Generate less garbage when expanding range bind variables in conditions
jeremy authored
435
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
436 def arel_table
437 @arel_table ||= Arel::Table.new(table_name, arel_engine)
438 end
2876707 @jeremy Pass a range in :conditions to use the SQL BETWEEN operator. Closes #…
jeremy authored
439
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
440 def arel_engine
441 @arel_engine ||= begin
442 if self == ActiveRecord::Base
443 ActiveRecord::Base
c2ed453 @dhh Fix quote_bound_value to not map Strings #1416 [htonl]
dhh authored
444 else
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
445 connection_handler.connection_pools[name] ? self : superclass.arel_engine
872ddaf @dhh Added bind-named arrays for interpolating a group of ids or strings i…
dhh authored
446 end
447 end
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
448 end
872ddaf @dhh Added bind-named arrays for interpolating a group of ids or strings i…
dhh authored
449
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
450 private
554597d @dhh Added named bind-style variable interpolation #281 [Michael Koziarski]
dhh authored
451
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
452 def relation #:nodoc:
453 @relation ||= Relation.new(self, arel_table)
454
455 if finder_needs_type_condition?
456 @relation.where(type_condition).create_with(inheritance_column.to_sym => sti_name)
457 else
458 @relation
aaf9a45 @dhh Added Base.validate_uniqueness thatv alidates whether the value of th…
dhh authored
459 end
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
460 end
db045db @dhh Initial
dhh authored
461 end
462
463 public
464 # New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
465 # attributes but not yet saved (pass a hash with key names matching the associated table column names).
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
466 # In both instances, valid attribute keys are determined by the column names of the associated table --
db045db @dhh Initial
dhh authored
467 # hence you can't have attributes that aren't part of the table columns.
7c5ae0a @joshk Added mass-assignment security :as and :without_protection support to…
joshk authored
468 #
469 # +initialize+ respects mass-assignment security and accepts either +:as+ or +:without_protection+ options
470 # in the +options+ parameter.
471 #
472 # ==== Examples
473 # # Instantiates a single new object
474 # User.new(:first_name => 'Jamie')
475 #
b2451f4 @joshk renamed mass-assignment scopes to roles, updated code, tests, docs an…
joshk authored
476 # # Instantiates a single new object using the :admin mass-assignment security role
7c5ae0a @joshk Added mass-assignment security :as and :without_protection support to…
joshk authored
477 # User.new({ :first_name => 'Jamie', :is_admin => true }, :as => :admin)
478 #
479 # # Instantiates a single new object bypassing mass-assignment security
480 # User.new({ :first_name => 'Jamie', :is_admin => true }, :without_protection => true)
481 def initialize(attributes = nil, options = {})
7edade3 @jonleighton Make read_attribute code path accessible at the class level
jonleighton authored
482 @attributes = self.class.initialize_attributes(self.class.column_defaults.dup)
839f3bf @tenderlove just use a hash for doing association caching
tenderlove authored
483 @association_cache = {}
344a2d5 @tenderlove use a hash for caching aggregations rather than ivars
tenderlove authored
484 @aggregation_cache = {}
5b801b5 @NZKoz Change the implementation of ActiveRecord's attribute reader and writ…
NZKoz authored
485 @attributes_cache = {}
e444439 @josevalim Partialy revert f1c13b0dd7b22b5f6289ca1a09f1d7a8c7c8584b
josevalim authored
486 @new_record = true
95bd56e @tenderlove speeding up clone_attributes, changing readonly to be initialized in …
tenderlove authored
487 @readonly = false
5de3698 @tenderlove cleaning up many more warnings in activerecord [#4180 state:resolved]
tenderlove authored
488 @destroyed = false
489 @marked_for_destruction = false
8c3e46c @tenderlove clean up more warnings, remove unnecessary methods, fix eval line num…
tenderlove authored
490 @previously_changed = {}
491 @changed_attributes = {}
5ddb60f @tenderlove initialize instance variables
tenderlove authored
492 @relation = nil
5de3698 @tenderlove cleaning up many more warnings in activerecord [#4180 state:resolved]
tenderlove authored
493
db045db @dhh Initial
dhh authored
494 ensure_proper_type
3da29f6 @lifo Remove AR#scope() method
lifo authored
495
cdfd013 @marklazz Set attributes properly for model built from association with conditi…
marklazz authored
496 populate_with_current_scope_attributes
7c5ae0a @joshk Added mass-assignment security :as and :without_protection support to…
joshk authored
497
498 assign_attributes(attributes, options) if attributes
3da29f6 @lifo Remove AR#scope() method
lifo authored
499
26caf32 @tenderlove remove useless assignment
tenderlove authored
500 yield self if block_given?
57bc25c @jfirebaugh Use run_callbacks; the generated _run_<name>_callbacks method is not …
jfirebaugh authored
501 run_callbacks :initialize
db045db @dhh Initial
dhh authored
502 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
503
04d37b0 @smartinez87 Remove extra whitespaces
smartinez87 authored
504 # Initialize an empty model object from +coder+. +coder+ must contain
505 # the attributes necessary for initializing an empty model object. For
505b532 @tenderlove speeding up object instantiation by eliminating instance_eval
tenderlove authored
506 # example:
507 #
508 # class Post < ActiveRecord::Base
509 # end
510 #
511 # post = Post.allocate
512 # post.init_with('attributes' => { 'title' => 'hello world' })
513 # post.title # => 'hello world'
514 def init_with(coder)
7edade3 @jonleighton Make read_attribute code path accessible at the class level
jonleighton authored
515 @attributes = self.class.initialize_attributes(coder['attributes'])
5ddb60f @tenderlove initialize instance variables
tenderlove authored
516 @relation = nil
5b42e96 @tenderlove make sure de-serialization happens on object instantiation
tenderlove authored
517
505b532 @tenderlove speeding up object instantiation by eliminating instance_eval
tenderlove authored
518 @attributes_cache, @previously_changed, @changed_attributes = {}, {}, {}
839f3bf @tenderlove just use a hash for doing association caching
tenderlove authored
519 @association_cache = {}
344a2d5 @tenderlove use a hash for caching aggregations rather than ivars
tenderlove authored
520 @aggregation_cache = {}
1f06652 @dchelimsky use persisted? instead of new_record? wherever possible
dchelimsky authored
521 @readonly = @destroyed = @marked_for_destruction = false
e444439 @josevalim Partialy revert f1c13b0dd7b22b5f6289ca1a09f1d7a8c7c8584b
josevalim authored
522 @new_record = false
57bc25c @jfirebaugh Use run_callbacks; the generated _run_<name>_callbacks method is not …
jfirebaugh authored
523 run_callbacks :find
524 run_callbacks :initialize
24485b9 @swistak Separated initialization
swistak authored
525
526 self
505b532 @tenderlove speeding up object instantiation by eliminating instance_eval
tenderlove authored
527 end
528
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
529 # Duped objects have no id assigned and are treated as new records. Note
530 # that this is a "shallow" copy as it copies the object's attributes
531 # only, not its associations. The extent of a "deep" copy is application
532 # specific and is therefore left to the application to implement according
533 # to its need.
534 # The dup method does not preserve the timestamps (created|updated)_(at|on).
535 def initialize_dup(other)
536 cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast)
77b4edc @jonleighton Fix attribute_before_type_cast for serialized attributes. Fixes #4837.
jonleighton authored
537 self.class.initialize_attributes(cloned_attributes)
538
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
539 cloned_attributes.delete(self.class.primary_key)
9e4b715 @josevalim Ensure assign_attributes and update_attributes do not fail on nil, cl…
josevalim authored
540
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
541 @attributes = cloned_attributes
a08d04b @joshk Added assign_attributes to Active Record which accepts a mass-assignm…
joshk authored
542
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
543 _run_after_initialize_callbacks if respond_to?(:_run_after_initialize_callbacks)
7367325 @jeremy Document Active Record exceptions. Closes #10444.
jeremy authored
544
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
545 @changed_attributes = {}
7edade3 @jonleighton Make read_attribute code path accessible at the class level
jonleighton authored
546 self.class.column_defaults.each do |attr, orig_value|
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
547 @changed_attributes[attr] = orig_value if field_changed?(attr, orig_value, @attributes[attr])
db045db @dhh Initial
dhh authored
548 end
3d0a9ff @dhh Aesthetics, baby
dhh authored
549
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
550 @aggregation_cache = {}
551 @association_cache = {}
552 @attributes_cache = {}
553 @new_record = true
774ff18 @akaspick Allow nested attributes in associations to update values in it's owne…
akaspick authored
554
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
555 ensure_proper_type
556 populate_with_current_scope_attributes
557 super
db045db @dhh Initial
dhh authored
558 end
559
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
560 # Backport dup from 1.9 so that initialize_dup() gets called
561 unless Object.respond_to?(:initialize_dup)
562 def dup # :nodoc:
563 copy = super
564 copy.initialize_dup(self)
565 copy
566 end
bd79a4e @dhh Fixed that clone would break when an aggregate had the same name as o…
dhh authored
567 end
568
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
569 # Populate +coder+ with attributes about this record that should be
570 # serialized. The structure of +coder+ defined in this method is
571 # guaranteed to match the structure of +coder+ passed to the +init_with+
572 # method.
39e1ac6 @lifo Merge docrails
lifo authored
573 #
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
574 # Example:
39e1ac6 @lifo Merge docrails
lifo authored
575 #
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
576 # class Post < ActiveRecord::Base
577 # end
578 # coder = {}
579 # Post.new.encode_with(coder)
580 # coder # => { 'id' => nil, ... }
581 def encode_with(coder)
582 coder['attributes'] = attributes
db045db @dhh Initial
dhh authored
583 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
584
d7db6a8 @joshk class inheritable attributes is used no more! all internal use of cla…
joshk authored
585 # Returns true if +comparison_object+ is the same exact object, or +comparison_object+
a820d0a @fxn revises RDoc of AR::Base#==
fxn authored
586 # is of the same type and +self+ has an ID and it is equal to +comparison_object.id+.
587 #
588 # Note that new records are different from any other record by definition, unless the
589 # other record is the receiver itself. Besides, if you fetch existing records with
590 # +select+ and leave the ID out, you're on your own, this predicate will return false.
591 #
592 # Note also that destroying a record preserves its ID in the model instance, so deleted
593 # models are still comparable.
db045db @dhh Initial
dhh authored
594 def ==(comparison_object)
8e19a5d @tenderlove call super rather than delegating to the other objects equal? method
tenderlove authored
595 super ||
4718d09 @spastorino Models should be equals even after destroyed
spastorino authored
596 comparison_object.instance_of?(self.class) &&
597 id.present? &&
598 comparison_object.id == id
db045db @dhh Initial
dhh authored
599 end
2545da6 @tenderlove just alias eql? to == for frewer method calls
tenderlove authored
600 alias :eql? :==
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
601
db045db @dhh Initial
dhh authored
602 # Delegates to id in order to allow two records of the same type and id to work with something like:
603 # [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
604 def hash
cfef86c @dhh Fixed bug in Base#hash method that would treat records with the same …
dhh authored
605 id.hash
db045db @dhh Initial
dhh authored
606 end
607
8c2177c Add documentation for freeze and readonly related methods. Closes #88…
Marcel Molina authored
608 # Freeze the attributes hash such that associations are still accessible, even on destroyed records.
24a9050 @dhh Changed the callbacks such that observers are notified before the in-…
dhh authored
609 def freeze
b1a4f91 @jamis Make destroy return self #1913 [sebastian.kanthak@muehlheim.de]
jamis authored
610 @attributes.freeze; self
24a9050 @dhh Changed the callbacks such that observers are notified before the in-…
dhh authored
611 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
612
8c2177c Add documentation for freeze and readonly related methods. Closes #88…
Marcel Molina authored
613 # Returns +true+ if the attributes hash has been frozen.
24a9050 @dhh Changed the callbacks such that observers are notified before the in-…
dhh authored
614 def frozen?
615 @attributes.frozen?
616 end
6e39c9e @jeremy r1614@asus: jeremy | 2005-07-03 08:01:08 -0700
jeremy authored
617
bc743dc @dmathieu allow comparison on model objects - Closes #1858
dmathieu authored
618 # Allows sort on objects
619 def <=>(other_object)
eb22c51 @dmathieu comparing different classes returns nil
dmathieu authored
620 if other_object.is_a?(self.class)
621 self.to_key <=> other_object.to_key
622 else
623 nil
624 end
bc743dc @dmathieu allow comparison on model objects - Closes #1858
dmathieu authored
625 end
626
8c2177c Add documentation for freeze and readonly related methods. Closes #88…
Marcel Molina authored
627 # Returns +true+ if the record is read only. Records loaded through joins with piggy-back
628 # attributes will be marked as read only since they cannot be saved.
64fcb75 @jeremy r3618@sedna: jeremy | 2005-10-14 12:06:03 -0700
jeremy authored
629 def readonly?
95bd56e @tenderlove speeding up clone_attributes, changing readonly to be initialized in …
tenderlove authored
630 @readonly
64fcb75 @jeremy r3618@sedna: jeremy | 2005-10-14 12:06:03 -0700
jeremy authored
631 end
632
8c2177c Add documentation for freeze and readonly related methods. Closes #88…
Marcel Molina authored
633 # Marks this record as read only.
634 def readonly!
64fcb75 @jeremy r3618@sedna: jeremy | 2005-10-14 12:06:03 -0700
jeremy authored
635 @readonly = true
636 end
d872281 @dhh Fixed to_xml across the board to use nice indention, better skip_attr…
dhh authored
637
8c2177c Add documentation for freeze and readonly related methods. Closes #88…
Marcel Molina authored
638 # Returns the contents of the record as a nicely formatted string.
e48b062 @jeremy Sanitize Base#inspect. Closes #8392.
jeremy authored
639 def inspect
b2db874 @franckverrot Fix the AR::Base#inspect method [closes #1294]
franckverrot authored
640 inspection = if @attributes
641 self.class.column_names.collect { |name|
642 if has_attribute?(name)
643 "#{name}: #{attribute_for_inspect(name)}"
644 end
645 }.compact.join(", ")
646 else
647 "not initialized"
648 end
649 "#<#{self.class} #{inspection}>"
e48b062 @jeremy Sanitize Base#inspect. Closes #8392.
jeremy authored
650 end
64fcb75 @jeremy r3618@sedna: jeremy | 2005-10-14 12:06:03 -0700
jeremy authored
651
52eedf5 @jonleighton Add hackery to make Syck use encode_with/init_with. Fixes 1.8 after r…
jonleighton authored
652 # Hackery to accomodate Syck. Remove for 4.0.
653 def to_yaml(opts = {}) #:nodoc:
654 if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck?
655 super
656 else
657 coder = {}
658 encode_with(coder)
659 YAML.quick_emit(self, opts) do |out|
660 out.map(taguri, to_yaml_style) do |map|
661 coder.each { |k, v| map.add(k, v) }
662 end
663 end
664 end
665 end
666
667 # Hackery to accomodate Syck. Remove for 4.0.
668 def yaml_initialize(tag, coder) #:nodoc:
669 init_with(coder)
670 end
671
db045db @dhh Initial
dhh authored
672 private
673
e9fa602 @jonleighton Define to_ary on ActiveRecord::Base to return nil. Improve performanc…
jonleighton authored
674 # Under Ruby 1.9, Array#flatten will call #to_ary (recursively) on each of the elements
675 # of the array, and then rescues from the possible NoMethodError. If those elements are
676 # ActiveRecord::Base's, then this triggers the various method_missing's that we have,
677 # which significantly impacts upon performance.
678 #
679 # So we can avoid the method_missing hit by explicitly defining #to_ary as nil here.
680 #
681 # See also http://tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary/
682 def to_ary # :nodoc:
683 nil
684 end
685
d916c62 @wycats eliminate alias_method_chain from ActiveRecord
wycats authored
686 include ActiveRecord::Persistence
1c4d28b @josh Move model naming into ActiveModel
josh authored
687 extend ActiveModel::Naming
aa002c0 @josh ActiveRecord::QueryCache middleware
josh authored
688 extend QueryCache::ClassMethods
a15e02d @josevalim Unify benchmark APIs.
josevalim authored
689 extend ActiveSupport::Benchmarkable
033e0a0 @josevalim ActiveRecord and ActionPack now use the new descendants implementation.
josevalim authored
690 extend ActiveSupport::DescendantsTracker
a15e02d @josevalim Unify benchmark APIs.
josevalim authored
691
ceb33f8 @jonleighton Split out most of the AR::Base code into separate modules :cake:
jonleighton authored
692 extend Querying
693 include ReadonlyAttributes
694 include ModelSchema
695 extend Translation
696 include Inheritance
697 include Scoping
698 extend DynamicMatchers
699 include Sanitization
700 include Integration
701 include AttributeAssignment
56bed51 @josevalim Fix dom_id for ActiveRecord [#4296 state:resolved]
josevalim authored
702 include ActiveModel::Conversion
7254d23 @josh Autoload ActiveRecord files
josh authored
703 include Validations
d916c62 @wycats eliminate alias_method_chain from ActiveRecord
wycats authored
704 extend CounterCache
7254d23 @josh Autoload ActiveRecord files
josh authored
705 include Locking::Optimistic, Locking::Pessimistic
706 include AttributeMethods
4d70359 @josh Integrate ActiveModel::Observing into ActiveRecord
josh authored
707 include Callbacks, ActiveModel::Observing, Timestamp
2b22564 @jonleighton Move DefaultScope and NamedScope under Scoping
jonleighton authored
708 include Associations
ce66bfd @swistak IdentityMap - misc fixes
swistak authored
709 include IdentityMap
bcf4e4f @dhh Added ActiveRecord::Base#has_secure_password (via ActiveModel::Secure…
dhh authored
710 include ActiveModel::SecurePassword
0065f37 @fxn AS::Concern is not really needed for AR::Explain
fxn authored
711 extend Explain
ec8f045 @alloy Add support for nested object forms to ActiveRecord and the helpers i…
alloy authored
712
713 # AutosaveAssociation needs to be included before Transactions, because we want
714 # #save_with_autosave_associations to be wrapped inside a transaction.
715 include AutosaveAssociation, NestedAttributes
85b64f9 @dhh Added ActiveRecord::Base.store for declaring simple single-column key…
dhh authored
716 include Aggregations, Transactions, Reflection, Serialization, Store
7254d23 @josh Autoload ActiveRecord files
josh authored
717 end
15aa6e0 @jeremy r4644@asus: jeremy | 2006-06-16 14:57:03 -0700
jeremy authored
718 end
d6b923a @josh get activerecord tests passing with lazy loading
josh authored
719
0d5a6f6 @jonleighton In 1efd88283ef68d912df215125951a87526768a51, ConnectionAdapters was p…
jonleighton authored
720 require 'active_record/connection_adapters/abstract/connection_specification'
4aded43 @wycats Replace the placeholder base_hook API with on_load. To specify some c…
wycats authored
721 ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Base)
Something went wrong with that request. Please try again.