1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge remote branch 'docrails/master'

This commit is contained in:
Xavier Noria 2010-09-01 00:01:26 +02:00
commit 8b2e4fddbf
4 changed files with 54 additions and 59 deletions

View file

@ -269,8 +269,9 @@ module ActionView
# The +options+ hash accepts the same options as url_for. # The +options+ hash accepts the same options as url_for.
# #
# There are a few special +html_options+: # There are a few special +html_options+:
# * <tt>:method</tt> - Specifies the anchor name to be appended to the path. # * <tt>:method</tt> - Symbol of HTTP verb. Supported verbs are <tt>:post</tt>, <tt>:get</tt>,
# * <tt>:disabled</tt> - Specifies the anchor name to be appended to the path. # <tt>:delete</tt> and <tt>:put</tt>. By default it will be <tt>:post</tt>.
# * <tt>:disabled</tt> - If set to true, it will generate a disabled button.
# * <tt>:confirm</tt> - This will use the unobtrusive JavaScript driver to # * <tt>:confirm</tt> - This will use the unobtrusive JavaScript driver to
# prompt with the question specified. If the user accepts, the link is # prompt with the question specified. If the user accepts, the link is
# processed normally, otherwise no action is taken. # processed normally, otherwise no action is taken.

View file

@ -234,7 +234,7 @@ h4. Array Conditions
Now what if that number could vary, say as an argument from somewhere, or perhaps from the user's level status somewhere? The find then becomes something like: Now what if that number could vary, say as an argument from somewhere, or perhaps from the user's level status somewhere? The find then becomes something like:
<ruby> <ruby>
Client.where(["orders_count = ?", params[:orders]]) Client.where("orders_count = ?", params[:orders])
</ruby> </ruby>
Active Record will go through the first element in the conditions value and any additional elements will replace the question marks +(?)+ in the first element. Active Record will go through the first element in the conditions value and any additional elements will replace the question marks +(?)+ in the first element.
@ -242,7 +242,7 @@ Active Record will go through the first element in the conditions value and any
Or if you want to specify two conditions, you can do it like: Or if you want to specify two conditions, you can do it like:
<ruby> <ruby>
Client.where(["orders_count = ? AND locked = ?", params[:orders], false]) Client.where("orders_count = ? AND locked = ?", params[:orders], false)
</ruby> </ruby>
In this example, the first question mark will be replaced with the value in +params[:orders]+ and the second will be replaced with the SQL representation of +false+, which depends on the adapter. In this example, the first question mark will be replaced with the value in +params[:orders]+ and the second will be replaced with the SQL representation of +false+, which depends on the adapter.
@ -250,7 +250,7 @@ In this example, the first question mark will be replaced with the value in +par
The reason for doing code like: The reason for doing code like:
<ruby> <ruby>
Client.where(["orders_count = ?", params[:orders]]) Client.where("orders_count = ?", params[:orders])
</ruby> </ruby>
instead of: instead of:
@ -268,8 +268,8 @@ h5. Placeholder Conditions
Similar to the +(?)+ replacement style of params, you can also specify keys/values hash in your array conditions: Similar to the +(?)+ replacement style of params, you can also specify keys/values hash in your array conditions:
<ruby> <ruby>
Client.where( Client.where("created_at >= :start_date AND created_at <= :end_date",
["created_at >= :start_date AND created_at <= :end_date", { :start_date => params[:start_date], :end_date => params[:end_date] }]) {:start_date => params[:start_date], :end_date => params[:end_date]})
</ruby> </ruby>
This makes for clearer readability if you have a large number of variable conditions. This makes for clearer readability if you have a large number of variable conditions.
@ -279,8 +279,8 @@ h5(#array-range_conditions). 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: 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:
<ruby> <ruby>
Client.where(["created_at IN (?)", Client.where("created_at IN (?)",
(params[:start_date].to_date)..(params[:end_date].to_date)]) (params[:start_date].to_date)..(params[:end_date].to_date))
</ruby> </ruby>
This would generate the proper query which is great for small ranges but not so good for larger ranges. For example if you pass in a range of date objects spanning a year that's 365 (or possibly 366, depending on the year) strings it will attempt to match your field against. This would generate the proper query which is great for small ranges but not so good for larger ranges. For example if you pass in a range of date objects spanning a year that's 365 (or possibly 366, depending on the year) strings it will attempt to match your field against.
@ -301,8 +301,8 @@ 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: 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:
<ruby> <ruby>
Client.where(["created_at IN (?)", Client.where("created_at IN (?)",
(params[:start_date].to_date.to_time)..(params[:end_date].to_date.to_time)]) (params[:start_date].to_date.to_time)..(params[:end_date].to_date.to_time))
</ruby> </ruby>
<sql> <sql>
@ -323,14 +323,14 @@ In this example it would be better to use greater-than and less-than operators i
<ruby> <ruby>
Client.where( Client.where(
["created_at > ? AND created_at < ?", params[:start_date], params[:end_date]]) "created_at > ? AND created_at < ?", params[:start_date], params[:end_date])
</ruby> </ruby>
You can also use the greater-than-or-equal-to and less-than-or-equal-to like this: You can also use the greater-than-or-equal-to and less-than-or-equal-to like this:
<ruby> <ruby>
Client.where( Client.where(
["created_at >= ? AND created_at <= ?", params[:start_date], params[:end_date]]) "created_at >= ? AND created_at <= ?", params[:start_date], params[:end_date])
</ruby> </ruby>
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. 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.
@ -344,13 +344,13 @@ NOTE: Only equality, range and subset checking are possible with Hash conditions
h5. Equality Conditions h5. Equality Conditions
<ruby> <ruby>
Client.where({ :locked => true }) Client.where(:locked => true)
</ruby> </ruby>
The field name can also be a string: The field name can also be a string:
<ruby> <ruby>
Client.where({ 'locked' => true }) Client.where('locked' => true)
</ruby> </ruby>
h5(#hash-range_conditions). Range Conditions h5(#hash-range_conditions). Range Conditions
@ -358,7 +358,7 @@ h5(#hash-range_conditions). 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. 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.
<ruby> <ruby>
Client.where({ :created_at => (Time.now.midnight - 1.day)..Time.now.midnight}) Client.where(:created_at => (Time.now.midnight - 1.day)..Time.now.midnight)
</ruby> </ruby>
This will find all clients created yesterday by using a +BETWEEN+ SQL statement: This will find all clients created yesterday by using a +BETWEEN+ SQL statement:
@ -374,7 +374,7 @@ h5. Subset Conditions
If you want to find records using the +IN+ expression you can pass an array to the conditions hash: If you want to find records using the +IN+ expression you can pass an array to the conditions hash:
<ruby> <ruby>
Client.where({ :orders_count => [1,3,5] }) Client.where(:orders_count => [1,3,5])
</ruby> </ruby>
This code will generate SQL like this: This code will generate SQL like this:
@ -496,7 +496,7 @@ SQL uses the +HAVING+ clause to specify conditions on the +GROUP BY+ fields. You
For example: For example:
<ruby> <ruby>
Order.group("date(created_at)".having(["created_at > ?", 1.month.ago]) Order.group("date(created_at)".having("created_at > ?", 1.month.ago)
</ruby> </ruby>
The SQL that would be executed would be something like this: The SQL that would be executed would be something like this:
@ -509,22 +509,16 @@ 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/destruction of the matching records returned in a Relation object, you could chain the +readonly+ method as +true+ to the find call. Active Record provides +readonly+ method on a relation to explicitly disallow modification or deletion of any of the returned object. Any attempt to alter or destroy a readonly record will not succeed, raising an +ActiveRecord::ReadOnlyRecord+ exception.
Any attempt to alter or destroy the readonly records will not succeed, raising an +ActiveRecord::ReadOnlyRecord+ exception. To set this option, specify it like this:
<ruby> <ruby>
Client.first.readonly(true) client = Client.readonly.first
</ruby> client.visits += 1
For example, calling the following code will raise an +ActiveRecord::ReadOnlyRecord+ exception:
<ruby>
client = Client.first.readonly(true)
client.locked = false
client.save client.save
</ruby> </ruby>
As +client+ is explicitly set to be a readonly object, the above code will raise an +ActiveRecord::ReadOnlyRecord+ exception when calling +client.save+ with an updated value of _visists_.
h4. Locking Records for Update h4. Locking Records for Update
Locking is helpful for preventing race conditions when updating records in the database and ensuring atomic updates. Locking is helpful for preventing race conditions when updating records in the database and ensuring atomic updates.
@ -571,13 +565,13 @@ end
h5. Pessimistic Locking h5. Pessimistic Locking
Pessimistic locking uses a locking mechanism provided by the underlying database. Passing +:lock => true+ to +Model.find+ obtains an exclusive lock on the selected rows. +Model.find+ using +:lock+ are usually wrapped inside a transaction for preventing deadlock conditions. Pessimistic locking uses a locking mechanism provided by the underlying database. Using +lock+ when building a relation obtains an exclusive lock on the selected rows. Relations using +lock+ are usually wrapped inside a transaction for preventing deadlock conditions.
For example: For example:
<ruby> <ruby>
Item.transaction do Item.transaction do
i = Item.first(:lock => true) i = Item.lock.first
i.name = 'Jones' i.name = 'Jones'
i.save i.save
end end
@ -592,25 +586,25 @@ Item Update (0.4ms) UPDATE `items` SET `updated_at` = '2009-02-07 18:05:56', `
SQL (0.8ms) COMMIT SQL (0.8ms) COMMIT
</sql> </sql>
You can also pass raw SQL to the +:lock+ option to allow different types of locks. For example, MySQL has an expression called +LOCK IN SHARE MODE+ where you can lock a record but still allow other queries to read it. To specify this expression just pass it in as the lock option: You can also pass raw SQL to the +lock+ method for allowing different types of locks. For example, MySQL has an expression called +LOCK IN SHARE MODE+ where you can lock a record but still allow other queries to read it. To specify this expression just pass it in as the lock option:
<ruby> <ruby>
Item.transaction do Item.transaction do
i = Item.find(1, :lock => "LOCK IN SHARE MODE") i = Item.lock("LOCK IN SHARE MODE").find(1)
i.increment!(:views) i.increment!(:views)
end end
</ruby> </ruby>
h3. Joining Tables h3. Joining Tables
<tt>Model.find</tt> provides a +:joins+ option for specifying +JOIN+ clauses on the resulting SQL. There are multiple ways to specify the +:joins+ option: Active Record provides a finder method called +joins+ for specifying +JOIN+ clauses on the resulting SQL. There are multiple ways to use the +joins+ method.
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: You can just supply the raw SQL specifying the +JOIN+ clause to +joins+:
<ruby> <ruby>
Client.all(:joins => 'LEFT OUTER JOIN addresses ON addresses.client_id = clients.id') Client.joins('LEFT OUTER JOIN addresses ON addresses.client_id = clients.id')
</ruby> </ruby>
This will result in the following SQL: This will result in the following SQL:
@ -625,7 +619,7 @@ WARNING: This method only works with +INNER JOIN+,
<br /> <br />
Active Record lets you use the names of the "associations":association_basics.html defined on the model as a shortcut for specifying the +:joins+ option. Active Record lets you use the names of the "associations":association_basics.html defined on the model as a shortcut for specifying +JOIN+ clause for those associations when using the +joins+ method.
For example, consider the following +Category+, +Post+, +Comments+ and +Guest+ models: For example, consider the following +Category+, +Post+, +Comments+ and +Guest+ models:
@ -838,13 +832,13 @@ Client.exists?(1,2,3)
Client.exists?([1,2,3]) Client.exists?([1,2,3])
</ruby> </ruby>
The +exists+ method may also take a +conditions+ option much like find: It's even possible to use +exists?+ without any arguments on a model or a relation.
<ruby> <ruby>
Client.exists?(:conditions => "first_name = 'Ryan'") Client.where(:first_name => 'Ryan').exists?
</ruby> </ruby>
It's even possible to use +exists?+ without any arguments: The above returns +true+ if there is at least one client with the +first_name+ 'Ryan' and +false+ otherwise.
<ruby> <ruby>
Client.exists? Client.exists?
@ -856,22 +850,24 @@ h3. Calculations
This section uses count as an example method in this preamble, but the options described apply to all sub-sections. This section uses count as an example method in this preamble, but the options described apply to all sub-sections.
<tt>count</tt> takes conditions much in the same way +exists?+ does: All calculation methods work directly on a model:
<ruby> <ruby>
Client.count(:conditions => "first_name = 'Ryan'") Client.count
# SELECT count(*) AS count_all FROM clients
</ruby> </ruby>
Which will execute: Or on a relation :
<sql>
SELECT count(*) AS count_all FROM clients WHERE (first_name = 'Ryan')
</sql>
You can also use the +includes+ or +joins+ methods for this to do something a little more complex:
<ruby> <ruby>
Client.where("clients.first_name = 'Ryan' AND orders.status = 'received'").includes("orders").count Client.where(:first_name => 'Ryan').count
# SELECT count(*) AS count_all FROM clients WHERE (first_name = 'Ryan')
</ruby>
You can also use various finder methods on a relation for performing complex calculations:
<ruby>
Client.includes("orders").where(:first_name => 'Ryan', :orders => {:status => 'received'}).count
</ruby> </ruby>
Which will execute: Which will execute:
@ -882,8 +878,6 @@ SELECT count(DISTINCT clients.id) AS count_all FROM clients
(clients.first_name = 'Ryan' AND orders.status = 'received') (clients.first_name = 'Ryan' AND orders.status = 'received')
</sql> </sql>
This code specifies +clients.first_name+ just in case one of the join tables has a field also called +first_name+ and it uses +orders.status+ because that's the name of our join table.
h4. Count h4. Count
If you want to see how many records are in your model's table you could call +Client.count+ and that will return the number. If you want to be more specific and find all the clients with their age present in the database you can use +Client.count(:age)+. If you want to see how many records are in your model's table you could call +Client.count+ and that will return the number. If you want to be more specific and find all the clients with their age present in the database you can use +Client.count(:age)+.

View file

@ -1087,7 +1087,7 @@ Partials are very useful in rendering collections. When you pass a collection to
When a partial is called with a pluralized collection, then the individual instances of the partial have access to the member of the collection being rendered via a variable named after the partial. In this case, the partial is +_product+, and within the +_product+ partial, you can refer to +product+ to get the instance that is being rendered. When a partial is called with a pluralized collection, then the individual instances of the partial have access to the member of the collection being rendered via a variable named after the partial. In this case, the partial is +_product+, and within the +_product+ partial, you can refer to +product+ to get the instance that is being rendered.
In Rails 3.0 there is also a shorthand for this, assuming +@posts+ is a collection of +post+ instances, you can simply do in the +index.html.erb+: In Rails 3.0 there is also a shorthand for this, assuming +@products+ is a collection of +product+ instances, you can simply do in the +index.html.erb+:
<erb> <erb>
<h1>Products</h1> <h1>Products</h1>

View file

@ -20,7 +20,7 @@ In a freshly generated Rails application, +test/performance/browsing_test.rb+ co
<ruby> <ruby>
require 'test_helper' require 'test_helper'
require 'performance_test_help' require 'rails/performance_test_help'
# Profiling results for each test method are written to tmp/performance. # Profiling results for each test method are written to tmp/performance.
class BrowsingTest < ActionController::PerformanceTest class BrowsingTest < ActionController::PerformanceTest
@ -34,17 +34,17 @@ This example is a simple performance test case for profiling a GET request to th
h4. Generating Performance Tests h4. Generating Performance Tests
Rails provides a generator called +performance_test+ for creating new performance tests: Rails provides a generator called +test_unit:performance+ for creating new performance tests:
<shell> <shell>
rails generate performance_test homepage rails generate test_unit:performance homepage
</shell> </shell>
This generates +homepage_test.rb+ in the +test/performance+ directory: This generates +homepage_test.rb+ in the +test/performance+ directory:
<ruby> <ruby>
require 'test_helper' require 'test_helper'
require 'performance_test_help' require 'rails/performance_test_help'
class HomepageTest < ActionController::PerformanceTest class HomepageTest < ActionController::PerformanceTest
# Replace this with your real tests. # Replace this with your real tests.
@ -103,7 +103,7 @@ Here's the performance test for +HomeController#dashboard+ and +PostsController#
<ruby> <ruby>
require 'test_helper' require 'test_helper'
require 'performance_test_help' require 'rails/performance_test_help'
class PostPerformanceTest < ActionController::PerformanceTest class PostPerformanceTest < ActionController::PerformanceTest
def setup def setup
@ -131,7 +131,7 @@ Performance test for +Post+ model:
<ruby> <ruby>
require 'test_helper' require 'test_helper'
require 'performance_test_help' require 'rails/performance_test_help'
class PostModelTest < ActionController::PerformanceTest class PostModelTest < ActionController::PerformanceTest
def test_creation def test_creation