aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--railties/guides/source/active_record_querying.textile70
1 files changed, 35 insertions, 35 deletions
diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile
index 5bf873b808..3d47cccc25 100644
--- a/railties/guides/source/active_record_querying.textile
+++ b/railties/guides/source/active_record_querying.textile
@@ -54,7 +54,7 @@ end
Active Record will perform queries on the database for you and is compatible with most database systems (MySQL, PostgreSQL and SQLite to name a few). Regardless of which database system you're using, the Active Record method format will always be the same.
-h3. Retrieving objects from the database
+h3. Retrieving Objects from the Database
To retrieve objects from the database, Active Record provides a class method called +Model.find+. This method allows you to pass arguments into it to perform certain queries on your database without the need of writing raw SQL.
@@ -65,11 +65,11 @@ Primary operation of <tt>Model.find(options)</tt> can be summarized as:
* Instantiate the equivalent Ruby object of the appropriate model for every resulting row.
* Run +after_find+ callbacks if any.
-h4. Retrieving a single object
+h4. Retrieving a Single Object
Active Record lets you retrieve a single object using three different ways.
-h5. Using a primary key
+h5. Using a Primary Key
Using <tt>Model.find(primary_key, options = nil)</tt>, you can retrieve the object corresponding to the supplied _primary key_ and matching the supplied options (if any). For example:
@@ -87,7 +87,7 @@ SELECT * FROM clients WHERE (clients.id = 10)
<tt>Model.find(primary_key)</tt> will raise an +ActiveRecord::RecordNotFound+ exception if no matching record is found.
-h5. Find first
+h5. +first+
<tt>Model.first(options = nil)</tt> finds the first record matched by the supplied options. If no +options+ are supplied, the first matching record is returned. For example:
@@ -106,7 +106,7 @@ SELECT * FROM clients LIMIT 1
NOTE: +Model.find(:first, options)+ is equivalent to +Model.first(options)+
-h5. Find last
+h5. +last+
<tt>Model.last(options = nil)</tt> finds the last record matched by the supplied options. If no +options+ are supplied, the last matching record is returned. For example:
@@ -126,9 +126,9 @@ SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1
NOTE: +Model.find(:last, options)+ is equivalent to +Model.last(options)+
-h4. Retrieving multiple objects
+h4. Retrieving Multiple Objects
-h5. Using multiple primary keys
+h5. Using Multiple Primary Keys
<tt>Model.find(array_of_primary_key, options = nil)</tt> also accepts an array of _primary keys_. An array of all the matching records for the supplied _primary keys_ is returned. For example:
@@ -166,7 +166,7 @@ SELECT * FROM clients
NOTE: +Model.find(:all, options)+ is equivalent to +Model.all(options)+
-h4. Retrieving multiple objects in batches
+h4. Retrieving Multiple Objects in Batches
Sometimes you need to iterate over a large set of records. For example to send a newsletter to all users, to export some data, etc.
@@ -238,13 +238,13 @@ h3. Conditions
The +find+ method allows you to specify conditions to limit the records returned, representing the WHERE-part of the SQL statement. Conditions can either be specified as a string, array, or hash.
-h4. Pure string conditions
+h4. Pure String Conditions
If you'd like to add conditions to your find, you could just specify them in there, just like +Client.first(:conditions => "orders_count = '2'")+. This will find all clients where the +orders_count+ field's value is 2.
WARNING: Building your own conditions as pure strings can leave you vulnerable to SQL injection exploits. For example, +Client.first(:conditions => "name LIKE '%#{params[:name]}%'")+ is not safe. See the next section for the preferred way to handle conditions using an array.
-h4. Array conditions
+h4. Array Conditions
Now what if that number could vary, say as a argument from somewhere, or perhaps from the user's level status somewhere? The find then becomes something like:
@@ -278,7 +278,7 @@ is because of argument safety. Putting the variable directly into the conditions
TIP: For more information on the dangers of SQL injection, see the "Ruby on Rails Security Guide":../security.html#_sql_injection.
-h5. Placeholder conditions
+h5. Placeholder Conditions
Similar to the +(?)+ replacement style of params, you can also specify keys/values hash in your Array conditions:
@@ -289,7 +289,7 @@ Client.all(:conditions =>
This makes for clearer readability if you have a large number of variable conditions.
-h5. Range conditions
+h5. Range Conditions
If you're looking for a range inside of a table (for example, users created in a certain timeframe) you can use the conditions option coupled with the +IN+ SQL statement for this. If you had two dates coming in from a controller you could do something like this to look for a range:
@@ -311,7 +311,7 @@ SELECT * FROM users WHERE (created_at IN
'2008-12-27','2008-12-28','2008-12-29','2008-12-30','2008-12-31'))
</sql>
-h5. Time and Date conditions
+h5. Time and Date Conditions
Things can get *really* messy if you pass in Time objects as it will attempt to compare your field to *every second* in that range:
@@ -350,13 +350,13 @@ Client.all(:conditions =>
Just like in Ruby. If you want a shorter syntax be sure to check out the "Hash Conditions":hash-conditions section later on in the guide.
-h4. Hash conditions
+h4. Hash Conditions
Active Record also allows you to pass in a hash conditions which can increase the readability of your conditions syntax. With hash conditions, you pass in a hash with keys of the fields you want conditionalised and the values of how you want to conditionalise them:
NOTE: Only equality, range and subset checking are possible with Hash conditions.
-h5. Equality conditions
+h5. Equality Conditions
<ruby>
Client.all(:conditions => { :locked => true })
@@ -368,7 +368,7 @@ The field name does not have to be a symbol it can also be a string:
Client.all(:conditions => { 'locked' => true })
</ruby>
-h5. Range conditions
+h5. Range Conditions
The good thing about this is that we can pass in a range for our fields without it generating a large query as shown in the preamble of this section.
@@ -384,7 +384,7 @@ SELECT * FROM clients WHERE (clients.created_at BETWEEN '2008-12-21 00:00:00' AN
This demonstrates a shorter syntax for the examples in "Array Conditions":#arrayconditions
-h5. Subset conditions
+h5. Subset Conditions
If you want to find records using the +IN+ expression you can pass an array to the conditions hash:
@@ -398,7 +398,7 @@ This code will generate SQL like this:
SELECT * FROM clients WHERE (clients.orders_count IN (1,3,5))
</sql>
-h3. Find options
+h3. Find Options
Apart from +:conditions+, +Model.find+ takes a variety of other options via the options hash for customizing the resulting record set.
@@ -438,7 +438,7 @@ Or ordering by multiple fields:
Client.all(:order => "orders_count ASC, created_at DESC")
</ruby>
-h4. Selecting specific fields
+h4. Selecting Specific Fields
By default, <tt>Model.find</tt> selects all the fields from the result set using +select *+.
@@ -538,7 +538,7 @@ SELECT * FROM orders GROUP BY date(created_at) HAVING created_at > '2009-01-15'
This will return single order objects for each day, but only for the last month.
-h4. Readonly objects
+h4. Readonly Objects
To explicitly disallow modification/destroyal of the matching records returned by +Model.find+, you could specify the +:readonly+ option as +true+ to the find call.
@@ -556,7 +556,7 @@ client.locked = false
client.save
</ruby>
-h4. Locking records for update
+h4. Locking Records for Update
Locking is helpful for preventing the race conditions when updating records in the database and ensuring atomic updated. Active Record provides two locking mechanism:
@@ -630,11 +630,11 @@ Item.transaction do
end
</ruby>
-h3. Joining tables
+h3. Joining Tables
<tt>Model.find</tt> provides a +:joins+ option for specifying +JOIN+ clauses on the resulting SQL. There multiple different ways to specify the +:joins+ option:
-h4. Using a string SQL fragment
+h4. Using a String SQL Fragment
You can just supply the raw SQL specifying the +JOIN+ clause to the +:joins+ option. For example:
@@ -648,7 +648,7 @@ This will result in the following SQL:
SELECT clients.* FROM clients INNER JOIN addresses ON addresses.client_id = clients.id
</sql>
-h4. Using Array/Hash of named associations
+h4. Using Array/Hash of Named Associations
WARNING: This method only works with +INNER JOIN+,
@@ -681,7 +681,7 @@ end
Now all of the following will produce the expected join queries using +INNER JOIN+:
-h5. Joining a single association
+h5. Joining a Single Association
<ruby>
Category.all :joins => :posts
@@ -694,7 +694,7 @@ SELECT categories.* FROM categories
INNER JOIN posts ON posts.category_id = categories.id
</sql>
-h5. Joining multiple associations
+h5. Joining Multiple Associations
<ruby>
Post.all :joins => [:category, :comments]
@@ -708,19 +708,19 @@ SELECT posts.* FROM posts
INNER JOIN comments ON comments.post_id = posts.id
</sql>
-h5. Joining nested associations (single level)
+h5. Joining Nested Associations (Single Level)
<ruby>
Post.all :joins => {:comments => :guest}
</ruby>
-h5. Joining nested associations (multiple level)
+h5. Joining Nested Associations (Multiple Level)
<ruby>
Category.all :joins => {:posts => [{:comments => :guest}, :tags]}
</ruby>
-h4. Specifying conditions on the joined tables
+h4. Specifying Conditions on the Joined Tables
You can specify conditions on the joined tables using the regular "Array":#arrayconditions and "String":#purestringconditions conditions. "Hash conditions":#hashconditions provides a special syntax for specifying conditions for the joined tables:
@@ -738,7 +738,7 @@ Client.all :joins => :orders, :conditions => {:orders => {:created_at => time_ra
This will find all clients who have orders that were created yesterday, again using a +BETWEEN+ SQL expression.
-h3. Eager loading associations
+h3. Eager Loading Associations
Eager loading is the mechanism for loading the associated records of the objects returned by +Model.find+ using as few queries as possible.
@@ -778,11 +778,11 @@ SELECT addresses.* FROM addresses
WHERE (addresses.client_id IN (1,2,3,4,5,6,7,8,9,10))
</sql>
-h4. Eager loading multiple associations
+h4. Eager Loading Multiple Associations
Active Record lets you eager load any possible number of associations with a single +Model.find+ call by using Array, Hash or a nested Hash of Array/Hash with +:include+ find option.
-h5. Array of multiple associations
+h5. Array of Multiple Associations
<ruby>
Post.all :include => [:category, :comments]
@@ -790,7 +790,7 @@ Post.all :include => [:category, :comments]
This loads all the posts and the associated category and comments for each post.
-h5. Nested assocaitions hash
+h5. Nested Assocaitions Hash
<ruby>
Category.find 1, :include => {:posts => [{:comments => :guest}, :tags]}
@@ -798,11 +798,11 @@ Category.find 1, :include => {:posts => [{:comments => :guest}, :tags]}
The above code finds the category with id 1 and eager loads all the posts associated with the found category. Additionally, it will also eager load every posts' tags and comments. Every comment's guest association will get eager loaded as well.
-h4. Specifying conditions on eager loaded associations
+h4. Specifying Conditions on Eager Loaded Associations
Even though Active Record lets you specify conditions on the eager loaded associations just like +:joins+, the recommended way is to use ":joins":#joiningtables instead.
-h3. Dynamic finders
+h3. Dynamic Finders
For every field (also known as an attribute) you define in your table, Active Record provides a finder method. If you have a field called +name+ on your Client model for example, you get +find_by_name+ and +find_all_by_name+ for free from Active Record. If you have also have a +locked+ field on the Client model, you also get +find_by_locked+ and +find_all_by_locked+.