aboutsummaryrefslogtreecommitdiffstats
path: root/guides/source
diff options
context:
space:
mode:
Diffstat (limited to 'guides/source')
-rw-r--r--guides/source/2_2_release_notes.textile4
-rw-r--r--guides/source/2_3_release_notes.textile2
-rw-r--r--guides/source/4_0_release_notes.textile47
-rw-r--r--guides/source/action_mailer_basics.textile4
-rw-r--r--guides/source/active_record_querying.textile45
-rw-r--r--guides/source/active_record_validations_callbacks.textile2
-rw-r--r--guides/source/active_support_core_extensions.textile22
-rw-r--r--guides/source/ajax_on_rails.textile9
-rw-r--r--guides/source/association_basics.textile34
-rw-r--r--guides/source/configuring.textile2
-rw-r--r--guides/source/contributing_to_ruby_on_rails.textile27
-rw-r--r--guides/source/debugging_rails_applications.textile6
-rw-r--r--guides/source/engines.textile38
-rw-r--r--guides/source/form_helpers.textile135
-rw-r--r--guides/source/getting_started.textile18
-rw-r--r--guides/source/i18n.textile2
-rw-r--r--guides/source/layouts_and_rendering.textile2
-rw-r--r--guides/source/migrations.textile47
-rw-r--r--guides/source/plugins.textile2
-rw-r--r--guides/source/security.textile2
-rw-r--r--guides/source/testing.textile88
21 files changed, 351 insertions, 187 deletions
diff --git a/guides/source/2_2_release_notes.textile b/guides/source/2_2_release_notes.textile
index 3a0f2efbaf..eb4b32329b 100644
--- a/guides/source/2_2_release_notes.textile
+++ b/guides/source/2_2_release_notes.textile
@@ -118,9 +118,9 @@ h4. Transactional Migrations
Historically, multiple-step Rails migrations have been a source of trouble. If something went wrong during a migration, everything before the error changed the database and everything after the error wasn't applied. Also, the migration version was stored as having been executed, which means that it couldn't be simply rerun by +rake db:migrate:redo+ after you fix the problem. Transactional migrations change this by wrapping migration steps in a DDL transaction, so that if any of them fail, the entire migration is undone. In Rails 2.2, transactional migrations are supported on PostgreSQL out of the box. The code is extensible to other database types in the future - and IBM has already extended it to support the DB2 adapter.
-* Lead Contributor: "Adam Wiggins":http://adam.blog.heroku.com/
+* Lead Contributor: "Adam Wiggins":http://adam.heroku.com/
* More information:
-** "DDL Transactions":http://adam.blog.heroku.com/past/2008/9/3/ddl_transactions/
+** "DDL Transactions":http://adam.heroku.com/past/2008/9/3/ddl_transactions/
** "A major milestone for DB2 on Rails":http://db2onrails.com/2008/11/08/a-major-milestone-for-db2-on-rails/
h4. Connection Pooling
diff --git a/guides/source/2_3_release_notes.textile b/guides/source/2_3_release_notes.textile
index 15abba66ab..36f425574b 100644
--- a/guides/source/2_3_release_notes.textile
+++ b/guides/source/2_3_release_notes.textile
@@ -561,7 +561,7 @@ This will layer the changes from the template on top of whatever code the projec
h4. Quieter Backtraces
-Building on Thoughtbot's "Quiet Backtrace":http://www.thoughtbot.com/projects/quietbacktrace plugin, which allows you to selectively remove lines from +Test::Unit+ backtraces, Rails 2.3 implements +ActiveSupport::BacktraceCleaner+ and +Rails::BacktraceCleaner+ in core. This supports both filters (to perform regex-based substitutions on backtrace lines) and silencers (to remove backtrace lines entirely). Rails automatically adds silencers to get rid of the most common noise in a new application, and builds a +config/backtrace_silencers.rb+ file to hold your own additions. This feature also enables prettier printing from any gem in the backtrace.
+Building on Thoughtbot's "Quiet Backtrace":https://github.com/thoughtbot/quietbacktrace plugin, which allows you to selectively remove lines from +Test::Unit+ backtraces, Rails 2.3 implements +ActiveSupport::BacktraceCleaner+ and +Rails::BacktraceCleaner+ in core. This supports both filters (to perform regex-based substitutions on backtrace lines) and silencers (to remove backtrace lines entirely). Rails automatically adds silencers to get rid of the most common noise in a new application, and builds a +config/backtrace_silencers.rb+ file to hold your own additions. This feature also enables prettier printing from any gem in the backtrace.
h4. Faster Boot Time in Development Mode with Lazy Loading/Autoload
diff --git a/guides/source/4_0_release_notes.textile b/guides/source/4_0_release_notes.textile
index e1d6b42e6c..d545798f6f 100644
--- a/guides/source/4_0_release_notes.textile
+++ b/guides/source/4_0_release_notes.textile
@@ -112,6 +112,8 @@ h4(#railties_deprecations). Deprecations
h3. Action Mailer
+* Allow to set default Action Mailer options via <tt>config.action_mailer.default_options=</tt>.
+
* Raise an <tt>ActionView::MissingTemplate</tt> exception when no implicit template could be found.
* Asynchronously send messages via the Rails Queue.
@@ -120,6 +122,16 @@ h3. Action Pack
h4. Action Controller
+* Add <tt>ActionController::Flash.add_flash_types</tt> method to allow people to register their own flash types. e.g.:
+
+<ruby>
+class ApplicationController
+ add_flash_types :error, :warning
+end
+</ruby>
+
+If you add the above code, you can use <tt><%= error %></tt> in an erb, and <tt>redirect_to /foo, :error => 'message'</tt> in a controller.
+
* Remove Active Model dependency from Action Pack.
* Support unicode characters in routes. Route will be automatically escaped, so instead of manually escaping:
@@ -184,6 +196,8 @@ h5(#actioncontroller_deprecations). Deprecations
h4. Action Dispatch
+* Show routes in exception page while debugging a <tt>RoutingError</tt> in development.
+
* Include <tt>mounted_helpers</tt> (helpers for accessing mounted engines) in <tt>ActionDispatch::IntegrationTest</tt> by default.
* Added <tt>ActionDispatch::SSL</tt> middleware that when included force all the requests to be under HTTPS protocol.
@@ -329,6 +343,20 @@ Moved into a separate gem <tt>sprockets-rails</tt>.
h3. Active Record
+* Add <tt>add_reference</tt> and <tt>remove_reference</tt> schema statements. Aliases, <tt>add_belongs_to</tt> and <tt>remove_belongs_to</tt> are acceptable. References are reversible.
+
+<ruby>
+# Create a user_id column
+add_reference(:products, :user)
+
+# Create a supplier_id, supplier_type columns and appropriate index
+add_reference(:products, :supplier, polymorphic: true, index: true)
+
+# Remove polymorphic reference
+remove_reference(:products, :supplier, polymorphic: true)
+</ruby>
+
+
* Add <tt>:default</tt> and <tt>:null</tt> options to <tt>column_exists?</tt>.
<ruby>
@@ -336,14 +364,19 @@ column_exists?(:testings, :taggable_id, :integer, null: false)
column_exists?(:testings, :taggable_type, :string, default: 'Photo')
</ruby>
-* <tt>ActiveRelation#inspect</tt> no longer calls <tt>#to_a</tt>. This means that in places where <tt>#inspect</tt> is implied (such as in the console), creating a relation will not execute it anymore, you'll have to call <tt>#to_a</tt> when necessary:
+* <tt>ActiveRecord::Relation#inspect</tt> now makes it clear that you are dealing with a <tt>Relation</tt> object rather than an array:
<ruby>
-User.where(:age => 30) # => returns the relation
-User.where(:age => 30).to_a # => executes the query and returns the loaded objects, as before
+User.where(:age => 30).inspect
+# => <ActiveRecord::Relation [#<User ...>, #<User ...>]>
+
+User.where(:age => 30).to_a.inspect
+# => [#<User ...>, #<User ...>]
</ruby>
-* Add <tt>collation</tt> and <tt>ctype</tt> support to PostgreSQL. These are available for PostgreSQL 8.4 or later.
+if more than 10 items are returned by the relation, inspect will only show the first 10 followed by ellipsis.
+
+* Add <tt>:collation</tt> and <tt>:ctype</tt> support to PostgreSQL. These are available for PostgreSQL 8.4 or later.
<yaml>
development:
@@ -506,7 +539,7 @@ Post.find_by! name: 'Spartacus'
* Added <tt>ActiveRecord::Base#slice</tt> to return a hash of the given methods with their names as keys and returned values as values.
-* Remove IdentityMap - IdentityMap has never graduated to be an "enabled-by-default" feature, due to some inconsistencies with associations, as described in this commit: https://github.com/rails/rails/commit/302c912bf6bcd0fa200d964ec2dc4a44abe328a6. Hence the removal from the codebase, until such issues are fixed.
+* Remove IdentityMap - IdentityMap has never graduated to be an "enabled-by-default" feature, due to some inconsistencies with associations, as described in this "commit":https://github.com/rails/rails/commit/302c912bf6bcd0fa200d964ec2dc4a44abe328a6. Hence the removal from the codebase, until such issues are fixed.
* Added a feature to dump/load internal state of +SchemaCache+ instance because we want to boot more quickly when we have many models.
@@ -666,6 +699,8 @@ where(...).remove_conditions # => still has conditions
* New rails application would be generated with the config.active_record.dependent_restrict_raises = false in the application config.
+* The migration generator now creates a join table with (commented) indexes every time the migration name contains the word "join_table".
+
h3. Active Model
* Changed <tt>AM::Serializers::JSON.include_root_in_json</tt> default value to false. Now, AM Serializers and AR objects have the same default behaviour.
@@ -708,7 +743,7 @@ h4(#activemodel_deprecations). Deprecations
h3. Active Resource
-* Active Resource is removed from Rails 4.0 and is now a separate gem. TODO: put a link to the gem here.
+* Active Resource is removed from Rails 4.0 and is now a separate "gem":https://github.com/rails/activeresource.
h3. Active Support
diff --git a/guides/source/action_mailer_basics.textile b/guides/source/action_mailer_basics.textile
index 7c61cc4a8d..54e55d7260 100644
--- a/guides/source/action_mailer_basics.textile
+++ b/guides/source/action_mailer_basics.textile
@@ -508,8 +508,8 @@ class UserMailerTest < ActionMailer::TestCase
# Test the body of the sent email contains what we expect it to
assert_equal [user.email], email.to
assert_equal "Welcome to My Awesome Site", email.subject
- assert_match(/<h1>Welcome to example.com, #{user.name}<\/h1>/, email.encoded)
- assert_match(/Welcome to example.com, #{user.name}/, email.encoded)
+ assert_match "<h1>Welcome to example.com, #{user.name}</h1>", email.body.to_s
+ assert_match "you have joined to example.com community", email.body.to_s
end
end
</ruby>
diff --git a/guides/source/active_record_querying.textile b/guides/source/active_record_querying.textile
index 101988c59e..b13932e8cb 100644
--- a/guides/source/active_record_querying.textile
+++ b/guides/source/active_record_querying.textile
@@ -12,8 +12,6 @@ This guide covers different ways to retrieve data from the database using Active
endprologue.
-WARNING. This Guide is based on Rails 3.0. Some of the code shown here will not work in other versions of Rails.
-
If you're used to using raw SQL to find database records, then you will generally find that there are better ways to carry out the same operations in Rails. Active Record insulates you from the need to use SQL in most cases.
Code examples throughout this guide will refer to one or more of the following models:
@@ -53,20 +51,26 @@ h3. Retrieving Objects from the Database
To retrieve objects from the database, Active Record provides several finder methods. Each finder method allows you to pass arguments into it to perform certain queries on your database without writing raw SQL.
The methods are:
-* +where+
-* +select+
+* +bind+
+* +create_with+
+* +extending+
+* +from+
* +group+
-* +order+
-* +reorder+
-* +reverse_order+
-* +limit+
-* +offset+
-* +joins+
+* +having+
* +includes+
+* +joins+
+* +limit+
* +lock+
+* +offset+
+* +order+
+* +none+
* +readonly+
-* +from+
-* +having+
+* +references+
+* +reorder+
+* +reverse_order+
+* +select+
+* +uniq+
+* +where+
All of the above methods return an instance of <tt>ActiveRecord::Relation</tt>.
@@ -1039,7 +1043,7 @@ Even though Active Record lets you specify conditions on the eager loaded associ
However if you must do this, you may use +where+ as you would normally.
<ruby>
-Post.includes(:comments).where("comments.visible", true)
+Post.includes(:comments).where("comments.visible" => true)
</ruby>
This would generate a query which contains a +LEFT OUTER JOIN+ whereas the +joins+ method would generate one using the +INNER JOIN+ function instead.
@@ -1128,21 +1132,6 @@ Using a class method is the preferred way to accept arguments for scopes. These
category.posts.created_before(time)
</ruby>
-h4. Working with scopes
-
-Where a relational object is required, the +scoped+ method may come in handy. This will return an +ActiveRecord::Relation+ object which can have further scoping applied to it afterwards. A place where this may come in handy is on associations
-
-<ruby>
-client = Client.find_by_first_name("Ryan")
-orders = client.orders.scoped
-</ruby>
-
-With this new +orders+ object, we are able to ascertain that this object can have more scopes applied to it. For instance, if we wanted to return orders only in the last 30 days at a later point.
-
-<ruby>
-orders.where("created_at > ?", 30.days.ago)
-</ruby>
-
h4. Applying a default scope
If we wish for a scope to be applied across all queries to the model we can use the +default_scope+ method within the model itself.
diff --git a/guides/source/active_record_validations_callbacks.textile b/guides/source/active_record_validations_callbacks.textile
index da3a96d84e..cf7293bd9e 100644
--- a/guides/source/active_record_validations_callbacks.textile
+++ b/guides/source/active_record_validations_callbacks.textile
@@ -86,6 +86,7 @@ The following methods skip validations, and will save the object to the database
* +update_all+
* +update_attribute+
* +update_column+
+* +update_columns+
* +update_counters+
Note that +save+ also has the ability to skip validations if passed +:validate => false+ as argument. This technique should be used with caution.
@@ -1084,6 +1085,7 @@ Just as with validations, it is also possible to skip callbacks. These methods s
* +toggle+
* +touch+
* +update_column+
+* +update_columns+
* +update_all+
* +update_counters+
diff --git a/guides/source/active_support_core_extensions.textile b/guides/source/active_support_core_extensions.textile
index 99b8bdd3fd..66de6fd310 100644
--- a/guides/source/active_support_core_extensions.textile
+++ b/guides/source/active_support_core_extensions.textile
@@ -2783,27 +2783,7 @@ The method +assert_valid_keys+ receives an arbitrary number of arguments, and ch
{:a => 1}.assert_valid_keys("a") # ArgumentError
</ruby>
-Active Record does not accept unknown options when building associations for example. It implements that control via +assert_valid_keys+:
-
-<ruby>
-mattr_accessor :valid_keys_for_has_many_association
-@@valid_keys_for_has_many_association = [
- :class_name, :table_name, :foreign_key, :primary_key,
- :dependent,
- :select, :conditions, :include, :order, :group, :having, :limit, :offset,
- :as, :through, :source, :source_type,
- :uniq,
- :finder_sql, :counter_sql,
- :before_add, :after_add, :before_remove, :after_remove,
- :extend, :readonly,
- :validate, :inverse_of
-]
-
-def create_has_many_reflection(association_id, options, &extension)
- options.assert_valid_keys(valid_keys_for_has_many_association)
- ...
-end
-</ruby>
+Active Record does not accept unknown options when building associations, for example. It implements that control via +assert_valid_keys+.
NOTE: Defined in +active_support/core_ext/hash/keys.rb+.
diff --git a/guides/source/ajax_on_rails.textile b/guides/source/ajax_on_rails.textile
index e23fdf9a74..26e0270a31 100644
--- a/guides/source/ajax_on_rails.textile
+++ b/guides/source/ajax_on_rails.textile
@@ -129,7 +129,7 @@ will produce
<ruby>
button_to 'Delete Image', { action: 'delete', id: @image.id },
- confirm: 'Are you sure?', method: :delete
+ method: :delete, data: { confirm: 'Are you sure?' }
</ruby>
will produce
@@ -144,8 +144,8 @@ will produce
</html>
<ruby>
-button_to 'Destroy', 'http://www.example.com', confirm: 'Are you sure?',
- method: 'delete', remote: true, data: { disable_with: 'loading...' }
+button_to 'Destroy', 'http://www.example.com',
+ method: 'delete', remote: true, data: { disable_with: 'loading...', confirm: 'Are you sure?' }
</ruby>
will produce
@@ -217,7 +217,6 @@ link_to_remote "Delete the item",
Note that if we wouldn't override the default behavior (POST), the above snippet would route to the create action rather than destroy.
** *JavaScript filters* You can customize the remote call further by wrapping it with some JavaScript code. Let's say in the previous example, when deleting a link, you'd like to ask for a confirmation by showing a simple modal text box to the user. This is a typical example what you can accomplish with these options - let's see them one by one:
-*** +:confirm+ =&gt; +msg+ Pops up a JavaScript confirmation dialog, displaying +msg+. If the user chooses 'OK', the request is launched, otherwise canceled.
*** +:condition+ =&gt; +code+ Evaluates +code+ (which should evaluate to a boolean) and proceeds if it's true, cancels the request otherwise.
*** +:before+ =&gt; +code+ Evaluates the +code+ just before launching the request. The output of the code has no influence on the execution. Typically used show a progress indicator (see this in action in the next example).
*** +:after+ =&gt; +code+ Evaluates the +code+ after launching the request. Note that this is different from the +:success+ or +:complete+ callback (covered in the next section) since those are triggered after the request is completed, while the code snippet passed to +:after+ is evaluated after the remote call is made. A common example is to disable elements on the page or otherwise prevent further action while the request is completed.
@@ -307,4 +306,4 @@ JavaScript testing reminds me the definition of the world 'classic' by Mark Twai
* Cucumber+Webrat
* Mention stuff like screw.unit/jsSpec
-Note to self: check out the RailsConf JS testing video \ No newline at end of file
+Note to self: check out the RailsConf JS testing video
diff --git a/guides/source/association_basics.textile b/guides/source/association_basics.textile
index 8ddc56bef1..4dca7a508c 100644
--- a/guides/source/association_basics.textile
+++ b/guides/source/association_basics.textile
@@ -1257,10 +1257,8 @@ The +has_many+ association supports these options:
* +:autosave+
* +:class_name+
* +:conditions+
-* +:counter_sql+
* +:dependent+
* +:extend+
-* +:finder_sql+
* +:foreign_key+
* +:group+
* +:include+
@@ -1326,12 +1324,6 @@ class Customer < ActiveRecord::Base
end
</ruby>
-h6(#has_many-counter_sql). +:counter_sql+
-
-Normally Rails automatically generates the proper SQL to count the association members. With the +:counter_sql+ option, you can specify a complete SQL statement to count them yourself.
-
-NOTE: If you specify +:finder_sql+ but not +:counter_sql+, then the counter SQL will be generated by substituting the +SELECT ... FROM+ clause of your +:finder_sql+ statement by +SELECT COUNT(*) FROM+.
-
h6(#has_many-dependent). +:dependent+
If you set the +:dependent+ option to +:destroy+, then deleting this object will call the +destroy+ method on the associated objects to delete those objects. If you set the +:dependent+ option to +:delete_all+, then deleting this object will delete the associated objects _without_ calling their +destroy+ method. If you set the +:dependent+ option to +:nullify+, then deleting this object will set the foreign key in the associated objects to +NULL+.
@@ -1345,10 +1337,6 @@ h6(#has_many-extend). +:extend+
The +:extend+ option specifies a named module to extend the association proxy. Association extensions are discussed in detail <a href="#association-extensions">later in this guide</a>.
-h6(#has_many-finder_sql). +:finder_sql+
-
-Normally Rails automatically generates the proper SQL to fetch the association members. With the +:finder_sql+ option, you can specify a complete SQL statement to fetch them yourself. If fetching objects requires complex multi-table SQL, this may be necessary.
-
h6(#has_many-foreign_key). +:foreign_key+
By convention, Rails assumes that the column used to hold the foreign key on the other model is the name of this model with the suffix +_id+ added. The +:foreign_key+ option lets you set the name of the foreign key directly:
@@ -1700,14 +1688,10 @@ The +has_and_belongs_to_many+ association supports these options:
* +:autosave+
* +:class_name+
* +:conditions+
-* +:counter_sql+
-* +:delete_sql+
* +:extend+
-* +:finder_sql+
* +:foreign_key+
* +:group+
* +:include+
-* +:insert_sql+
* +:join_table+
* +:limit+
* +:offset+
@@ -1767,24 +1751,10 @@ end
If you use a hash-style +:conditions+ option, then record creation via this association will be automatically scoped using the hash. In this case, using +@parts.assemblies.create+ or +@parts.assemblies.build+ will create orders where the +factory+ column has the value "Seattle".
-h6(#has_and_belongs_to_many-counter_sql). +:counter_sql+
-
-Normally Rails automatically generates the proper SQL to count the association members. With the +:counter_sql+ option, you can specify a complete SQL statement to count them yourself.
-
-NOTE: If you specify +:finder_sql+ but not +:counter_sql+, then the counter SQL will be generated by substituting the +SELECT ... FROM+ clause of your +:finder_sql+ statement by +SELECT COUNT(*) FROM+.
-
-h6(#has_and_belongs_to_many-delete_sql). +:delete_sql+
-
-Normally Rails automatically generates the proper SQL to remove links between the associated classes. With the +:delete_sql+ option, you can specify a complete SQL statement to delete them yourself.
-
h6(#has_and_belongs_to_many-extend). +:extend+
The +:extend+ option specifies a named module to extend the association proxy. Association extensions are discussed in detail <a href="#association-extensions">later in this guide</a>.
-h6(#has_and_belongs_to_many-finder_sql). +:finder_sql+
-
-Normally Rails automatically generates the proper SQL to fetch the association members. With the +:finder_sql+ option, you can specify a complete SQL statement to fetch them yourself. If fetching objects requires complex multi-table SQL, this may be necessary.
-
h6(#has_and_belongs_to_many-foreign_key). +:foreign_key+
By convention, Rails assumes that the column in the join table used to hold the foreign key pointing to this model is the name of this model with the suffix +_id+ added. The +:foreign_key+ option lets you set the name of the foreign key directly:
@@ -1811,10 +1781,6 @@ h6(#has_and_belongs_to_many-include). +:include+
You can use the +:include+ option to specify second-order associations that should be eager-loaded when this association is used.
-h6(#has_and_belongs_to_many-insert_sql). +:insert_sql+
-
-Normally Rails automatically generates the proper SQL to create links between the associated classes. With the +:insert_sql+ option, you can specify a complete SQL statement to insert them yourself.
-
h6(#has_and_belongs_to_many-join_table). +:join_table+
If the default name of the join table, based on lexical ordering, is not what you want, you can use the +:join_table+ option to override the default.
diff --git a/guides/source/configuring.textile b/guides/source/configuring.textile
index af46538bf5..cd9aab4892 100644
--- a/guides/source/configuring.textile
+++ b/guides/source/configuring.textile
@@ -424,7 +424,7 @@ There are a number of settings available on +config.action_mailer+:
* +config.action_mailer.perform_deliveries+ specifies whether mail will actually be delivered and is true by default. It can be convenient to set it to false for testing.
-* +config.action_mailer.default+ configures Action Mailer defaults. These default to:
+* +config.action_mailer.default_options+ configures Action Mailer defaults. Use to set options like `from` or `reply_to` for every mailer. These default to:
<ruby>
:mime_version => "1.0",
:charset => "UTF-8",
diff --git a/guides/source/contributing_to_ruby_on_rails.textile b/guides/source/contributing_to_ruby_on_rails.textile
index 1dadce2083..a8a097d156 100644
--- a/guides/source/contributing_to_ruby_on_rails.textile
+++ b/guides/source/contributing_to_ruby_on_rails.textile
@@ -34,6 +34,8 @@ h4. What about Feature Requests?
Please don't put "feature request" items into GitHub Issues. If there's a new feature that you want to see added to Ruby on Rails, you'll need to write the code yourself - or convince someone else to partner with you to write the code. Later in this guide you'll find detailed instructions for proposing a patch to Ruby on Rails. If you enter a wishlist item in GitHub Issues with no code, you can expect it to be marked "invalid" as soon as it's reviewed.
+If you'd like feedback on an idea for a feature before doing the work for make a patch, please send an email to the "rails-core mailing list":https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core. You might get no response, which means that everyone is indifferent. You might find someone who's also interested in building that feature. You might get a "This won't be accepted." But it's the proper place to discuss new ideas. GitHub Issues are not a particularly good venue for the sometimes long and involved discussions new features require.
+
h3. Running the Test Suite
To move on from submitting bugs to helping resolve existing issues or contributing your own code to Ruby on Rails, you _must_ be able to run its test suite. In this section of the guide you'll learn how to set up the tests on your own computer.
@@ -66,12 +68,26 @@ Install first libxml2 and libxslt together with their development files for Noko
$ sudo apt-get install libxml2 libxml2-dev libxslt1-dev
</shell>
+If you are on Fedora or CentOS, you can run
+
+<shell>
+$ sudo yum install libxml2 libxml2-devel libxslt libxslt-devel
+</shell>
+
+If you have any problems with these libraries, you should install them manually compiling the source code. Just follow the instructions "here":http://nokogiri.org/tutorials/installing_nokogiri.html#red_hat__centos .
+
Also, SQLite3 and its development files for the +sqlite3-ruby+ gem -- in Ubuntu you're done with just
<shell>
$ sudo apt-get install sqlite3 libsqlite3-dev
</shell>
+And if you are on Fedora or CentOS, you're done with
+
+<shell>
+$ sudo yum install sqlite3 sqlite3-devel
+</shell>
+
Get a recent version of "Bundler":http://gembundler.com/:
<shell>
@@ -150,6 +166,13 @@ $ sudo apt-get install mysql-server libmysqlclient15-dev
$ sudo apt-get install postgresql postgresql-client postgresql-contrib libpq-dev
</shell>
+On Fedora or CentOS, just run:
+
+<shell>
+$ sudo yum install mysql-server mysql-devel
+$ sudo yum install postgresql-server postgresql-devel
+</shell>
+
After that run:
<shell>
@@ -172,7 +195,7 @@ and create the test databases:
<shell>
$ cd activerecord
-$ rake mysql:build_databases
+$ bundle exec rake mysql:build_databases
</shell>
PostgreSQL's authentication works differently. A simple way to set up the development environment for example is to run with your development account
@@ -185,7 +208,7 @@ and then create the test databases with
<shell>
$ cd activerecord
-$ rake postgresql:build_databases
+$ bundle exec rake postgresql:build_databases
</shell>
NOTE: Using the rake task to create the test databases ensures they have the correct character set and collation.
diff --git a/guides/source/debugging_rails_applications.textile b/guides/source/debugging_rails_applications.textile
index cc172042e9..667f2d2140 100644
--- a/guides/source/debugging_rails_applications.textile
+++ b/guides/source/debugging_rails_applications.textile
@@ -626,7 +626,7 @@ In this section, you will learn how to find and fix such leaks by using tools su
h4. BleakHouse
-"BleakHouse":https://github.com/fauna/bleak_house/tree/master is a library for finding memory leaks.
+"BleakHouse":https://github.com/evan/bleak_house/ is a library for finding memory leaks.
If a Ruby object does not go out of scope, the Ruby Garbage Collector won't sweep it since it is referenced somewhere. Leaks like this can grow slowly and your application will consume more and more memory, gradually affecting the overall system performance. This tool will help you find leaks on the Ruby heap.
@@ -675,7 +675,7 @@ To analyze it, just run the listed command. The top 20 leakiest lines will be li
This way you can find where your application is leaking memory and fix it.
-If "BleakHouse":https://github.com/fauna/bleak_house/tree/master doesn't report any heap growth but you still have memory growth, you might have a broken C extension, or real leak in the interpreter. In that case, try using Valgrind to investigate further.
+If "BleakHouse":https://github.com/evan/bleak_house/ doesn't report any heap growth but you still have memory growth, you might have a broken C extension, or real leak in the interpreter. In that case, try using Valgrind to investigate further.
h4. Valgrind
@@ -708,4 +708,4 @@ h3. References
* "Debugging with ruby-debug":http://bashdb.sourceforge.net/ruby-debug.html
* "ruby-debug cheat sheet":http://cheat.errtheblog.com/s/rdebug/
* "Ruby on Rails Wiki: How to Configure Logging":http://wiki.rubyonrails.org/rails/pages/HowtoConfigureLogging
-* "Bleak House Documentation":http://blog.evanweaver.com/files/doc/fauna/bleak_house/files/README.html
+* "Bleak House Documentation":http://blog.evanweaver.com/files/doc/fauna/bleak_house/
diff --git a/guides/source/engines.textile b/guides/source/engines.textile
index 86e7254201..53c2845731 100644
--- a/guides/source/engines.textile
+++ b/guides/source/engines.textile
@@ -347,7 +347,7 @@ The form will be making a +POST+ request to +/posts/:post_id/comments+, which wi
<ruby>
def create
@post = Post.find(params[:post_id])
- @comment = @post.comments.build(params[:comment])
+ @comment = @post.comments.create(params[:comment])
flash[:notice] = "Comment has been created!"
redirect_to post_path
end
@@ -563,7 +563,7 @@ end
By default, the engine's controllers inherit from <tt>Blorgh::ApplicationController</tt>. So, after making this change they will have access to the main applications +ApplicationController+ as though they were part of the main application.
-This change does require that the engine is run from a Rails application that has an +ApplicationController+.
+This change does require that the engine is run from a Rails application that has an +ApplicationController+.
h4. Configuring an engine
@@ -734,12 +734,14 @@ You can also specify these assets as dependencies of other assets using the Asse
*/
</plain>
+INFO. Remember that in order to use languages like Sass or CoffeeScript, you should add the relevant library to your engine's +.gemspec+.
+
h4. Separate Assets & Precompiling
There are some situations where your engine's assets not required by the host application. For example, say that you've created
an admin functionality that only exists for your engine. In this case, the host application doesn't need to require +admin.css+
or +admin.js+. Only the gem's admin layout needs these assets. It doesn't make sense for the host app to include +"blorg/admin.css"+ in it's stylesheets. In this situation, you should explicitly define these assets for precompilation.
-This tells sprockets to add you engine assets when +rake assets:precompile+ is ran.
+This tells sprockets to add you engine assets when +rake assets:precompile+ is ran.
You can define assets for precompilation in +engine.rb+
@@ -753,18 +755,40 @@ For more information, read the "Asset Pipeline guide":http://guides.rubyonrails.
h4. Other gem dependencies
-Gem dependencies inside an engine should be specified inside the +.gemspec+ file that's at the root of the engine. The reason for this is because the engine may be installed as a gem. If dependencies were to be specified inside the +Gemfile+, these would not be recognised by a traditional gem install and so they would not be installed, causing the engine to malfunction.
+Gem dependencies inside an engine should be specified inside the +.gemspec+ file
+that's at the root of the engine. The reason for this is because the engine may
+be installed as a gem. If dependencies were to be specified inside the +Gemfile+,
+these would not be recognised by a traditional gem install and so they would not
+be installed, causing the engine to malfunction.
-To specify a dependency that should be installed with the engine during a traditional +gem install+, specify it inside the +Gem::Specification+ block inside the +.gemspec+ file in the engine:
+To specify a dependency that should be installed with the engine during a
+traditional +gem install+, specify it inside the +Gem::Specification+ block
+inside the +.gemspec+ file in the engine:
<ruby>
s.add_dependency "moo"
</ruby>
-To specify a dependency that should only be installed as a development dependency of the application, specify it like this:
+To specify a dependency that should only be installed as a development
+dependency of the application, specify it like this:
<ruby>
s.add_development_dependency "moo"
</ruby>
-Both kinds of dependencies will be installed when +bundle install+ is run inside the application. The development dependencies for the gem will only be used when the tests for the engine are running.
+Both kinds of dependencies will be installed when +bundle install+ is run inside
+the application. The development dependencies for the gem will only be used when
+the tests for the engine are running.
+
+Note that if you want to immediately require dependencies when the engine is
+required, you should require them before engine's initialization. For example:
+
+<ruby>
+require 'other_engine/engine'
+require 'yet_another_engine/engine'
+
+module MyEngine
+ class Engine < ::Rails::Engine
+ end
+end
+</ruby> \ No newline at end of file
diff --git a/guides/source/form_helpers.textile b/guides/source/form_helpers.textile
index 1851aceff8..58338ce54b 100644
--- a/guides/source/form_helpers.textile
+++ b/guides/source/form_helpers.textile
@@ -10,7 +10,7 @@ In this guide you will:
* Understand the date and time helpers Rails provides
* Learn what makes a file upload form different
* Learn some cases of building forms to external resources
-* Find out where to look for complex forms
+* Find out how to build complex forms
endprologue.
@@ -816,11 +816,130 @@ Or if you don't want to render an +authenticity_token+ field:
h3. Building Complex Forms
-Many apps grow beyond simple forms editing a single object. For example when creating a Person you might want to allow the user to (on the same form) create multiple address records (home, work, etc.). When later editing that person the user should be able to add, remove or amend addresses as necessary. While this guide has shown you all the pieces necessary to handle this, Rails does not yet have a standard end-to-end way of accomplishing this, but many have come up with viable approaches. These include:
+Many apps grow beyond simple forms editing a single object. For example when creating a Person you might want to allow the user to (on the same form) create multiple address records (home, work, etc.). When later editing that person the user should be able to add, remove or amend addresses as necessary.
-* As of Rails 2.3, Rails includes "Nested Attributes":./2_3_release_notes.html#nested-attributes and "Nested Object Forms":./2_3_release_notes.html#nested-object-forms
-* Ryan Bates' series of Railscasts on "complex forms":http://railscasts.com/episodes/75
-* Handle Multiple Models in One Form from "Advanced Rails Recipes":http://media.pragprog.com/titles/fr_arr/multiple_models_one_form.pdf
-* Eloy Duran's "complex-forms-examples":https://github.com/alloy/complex-form-examples/ application
-* Lance Ivy's "nested_assignment":https://github.com/cainlevy/nested_assignment/tree/master plugin and "sample application":https://github.com/cainlevy/complex-form-examples/tree/cainlevy
-* James Golick's "attribute_fu":https://github.com/jamesgolick/attribute_fu plugin
+h4. Configuring the Model
+
+Active Record provides model level support via the +accepts_nested_attributes_for+ method:
+
+<ruby>
+class Person < ActiveRecord::Base
+ has_many :addresses
+ accepts_nested_attributes_for :addresses
+
+ attr_accessible :name, :addresses_attributes
+end
+
+class Address < ActiveRecord::Base
+ belongs_to :person
+ attr_accessible :kind, :street
+end
+</ruby>
+
+This creates an +addresses_attributes=+ method on +Person+ that allows you to create, update and (optionally) destroy addresses. When using +attr_accessible+ or +attr_protected+ you must mark +addresses_attributes+ as accessible as well as the other attributes of +Person+ and +Address+ that should be mass assigned.
+
+h4. Building the Form
+
+The following form allows a user to create a +Person+ and its associated addresses.
+
+<erb>
+<%= form_for @person do |f| %>
+ Addresses:
+ <ul>
+ <%= f.fields_for :addresses do |addresses_form| %>
+ <li>
+ <%= addresses_form.label :kind %>
+ <%= addresses_form.text_field :kind %>
+
+ <%= addresses_form.label :street %>
+ <%= addresses_form.text_field :street %>
+ ...
+ </li>
+ <% end %>
+ </ul>
+<% end %>
+</erb>
+
+
+When an association accepts nested attributes +fields_for+ renders its block once for every element of the association. In particular, if a person has no addresses it renders nothing. A common pattern is for the controller to build one or more empty children so that at least one set of fields is shown to the user. The example below would result in 3 sets of address fields being rendered on the new person form.
+
+<ruby>
+def new
+ @person = Person.new
+ 3.times { @person.addresses.build}
+end
+</ruby>
+
++fields_for+ yields a form builder that names parameters in the format expected the accessor generated by +accepts_nested_attributes_for+. For example when creating a user with 2 addresses, the submitted parameters would look like
+
+<ruby>
+{
+ :person => {
+ :name => 'John Doe',
+ :addresses_attributes => {
+ '0' => {
+ :kind => 'Home',
+ :street => '221b Baker Street',
+ },
+ '1' => {
+ :kind => 'Office',
+ :street => '31 Spooner Street'
+ }
+ }
+ }
+}
+</ruby>
+
+The keys of the +:addresses_attributes+ hash are unimportant, they need merely be different for each address.
+
+If the associated object is already saved, +fields_for+ autogenerates a hidden input with the +id+ of the saved record. You can disable this by passing +:include_id => false+ to +fields_for+. You may wish to do this if the autogenerated input is placed in a location where an input tag is not valid HTML or when using an ORM where children do not have an id.
+
+h4. The Controller
+
+You do not need to write any specific controller code to use nested attributes. Create and update records as you would with a simple form.
+
+h4. Removing Objects
+
+You can allow users to delete associated objects by passing +allow_destroy => true+ to +accepts_nested_attributes_for+
+
+<ruby>
+class Person < ActiveRecord::Base
+ has_many :addresses
+ accepts_nested_attributes_for :addresses, :allow_destroy => true
+end
+</ruby>
+
+If the hash of attributes for an object contains the key +_destroy+ with a value of '1' or 'true' then the object will be destroyed. This form allows users to remove addresses:
+
+<erb>
+<%= form_for @person do |f| %>
+ Addresses:
+ <ul>
+ <%= f.fields_for :addresses do |addresses_form| %>
+ <li>
+ <%= check_box :_destroy%>
+ <%= addresses_form.label :kind %>
+ <%= addresses_form.text_field :kind %>
+ ...
+ </li>
+ <% end %>
+ </ul>
+<% end %>
+</erb>
+
+h4. Preventing Empty Records
+
+It is often useful to ignore sets of fields that the user has not filled in. You can control this by passing a +:reject_if+ proc to +accepts_nested_attributes_for+. This proc will be called with each hash of attributes submitted by the form. If the proc returns +false+ then Active Record will not build an associated object for that hash. The example below only tries to build an address if the +kind+ attribute is set.
+
+<ruby>
+class Person < ActiveRecord::Base
+ has_many :addresses
+ accepts_nested_attributes_for :addresses, :reject_if => lambda {|attributes| attributes['kind'].blank?}
+end
+</ruby>
+
+As a convenience you can instead pass the symbol +:all_blank+ which will create a proc that will reject records where all the attributes are blank excluding any value for +_destroy+.
+
+h4. Adding Fields on the Fly
+
+Rather than rendering multiple sets of fields ahead of time you may wish to add them only when a user clicks on an 'Add new child' button. Rails does not provide any builtin support for this. When generating new sets of fields you must ensure the the key of the associated array is unique - the current javascript date (milliseconds after the epoch) is a common choice. \ No newline at end of file
diff --git a/guides/source/getting_started.textile b/guides/source/getting_started.textile
index 07419d11b4..8d7c0d4bea 100644
--- a/guides/source/getting_started.textile
+++ b/guides/source/getting_started.textile
@@ -1144,7 +1144,7 @@ together.
<td><%= post.text %></td>
<td><%= link_to 'Show', :action => :show, :id => post.id %></td>
<td><%= link_to 'Edit', :action => :edit, :id => post.id %></td>
- <td><%= link_to 'Destroy', { :action => :destroy, :id => post.id }, :method => :delete, :confirm => 'Are you sure?' %></td>
+ <td><%= link_to 'Destroy', { :action => :destroy, :id => post.id }, :method => :delete, :data => { :confirm => 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
@@ -1152,13 +1152,12 @@ together.
Here we're using +link_to+ in a different way. We wrap the
+:action+ and +:id+ attributes in a hash so that we can pass those two keys in
-first as one argument, and then the final two keys as another argument. The +:method+ and +:confirm+
+first as one argument, and then the final two keys as another argument. The +:method+ and +:'data-confirm'+
options are used as HTML5 attributes so that when the link is clicked,
-Rails will first show a confirm dialog to the user, and then submit the
-link with method +delete+. This is done via the JavaScript file +jquery_ujs+
-which is automatically included into your application's layout
-(+app/views/layouts/application.html.erb+) when you generated the application.
-Without this file, the confirmation dialog box wouldn't appear.
+Rails will first show a confirm dialog to the user, and then submit the link with method +delete+.
+This is done via the JavaScript file +jquery_ujs+ which is automatically included
+into your application's layout (+app/views/layouts/application.html.erb+) when you
+generated the application. Without this file, the confirmation dialog box wouldn't appear.
!images/getting_started/confirm_dialog.png(Confirm Dialog)!
@@ -1248,6 +1247,7 @@ First, take a look at +comment.rb+:
<ruby>
class Comment < ActiveRecord::Base
belongs_to :post
+ attr_accessible :body, :commenter
end
</ruby>
@@ -1626,8 +1626,8 @@ So first, let's add the delete link in the
<p>
<%= link_to 'Destroy Comment', [comment.post, comment],
- :confirm => 'Are you sure?',
- :method => :delete %>
+ :method => :delete,
+ :data => { :confirm => 'Are you sure?' } %>
</p>
</erb>
diff --git a/guides/source/i18n.textile b/guides/source/i18n.textile
index ee7176a6c8..8ad6ee4b73 100644
--- a/guides/source/i18n.textile
+++ b/guides/source/i18n.textile
@@ -220,7 +220,7 @@ Every helper method dependent on +url_for+ (e.g. helpers for named routes like +
You may be satisfied with this. It does impact the readability of URLs, though, when the locale "hangs" at the end of every URL in your application. Moreover, from the architectural standpoint, locale is usually hierarchically above the other parts of the application domain: and URLs should reflect this.
-You probably want URLs to look like this: +www.example.com/en/books+ (which loads the English locale) and +www.example.com/nl/books+ (which loads the Dutch locale). This is achievable with the "over-riding +default_url_options+" strategy from above: you just have to set up your routes with "+path_prefix+":http://api.rubyonrails.org/classes/ActionController/Resources.html#M000354 option in this way:
+You probably want URLs to look like this: +www.example.com/en/books+ (which loads the English locale) and +www.example.com/nl/books+ (which loads the Dutch locale). This is achievable with the "over-riding +default_url_options+" strategy from above: you just have to set up your routes with "+scoping+":http://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Scoping.html option in this way:
<ruby>
# config/routes.rb
diff --git a/guides/source/layouts_and_rendering.textile b/guides/source/layouts_and_rendering.textile
index 55bd521419..32ceecea18 100644
--- a/guides/source/layouts_and_rendering.textile
+++ b/guides/source/layouts_and_rendering.textile
@@ -78,7 +78,7 @@ If we want to display the properties of all the books in our view, we can do so
<td><%= book.content %></td>
<td><%= link_to "Show", book %></td>
<td><%= link_to "Edit", edit_book_path(book) %></td>
- <td><%= link_to "Remove", book, :confirm => "Are you sure?", :method => :delete %></td>
+ <td><%= link_to "Remove", book, :method => :delete, :data => { :confirm => "Are you sure?" } %></td>
</tr>
<% end %>
</table>
diff --git a/guides/source/migrations.textile b/guides/source/migrations.textile
index 342b5a4d57..06e85e5914 100644
--- a/guides/source/migrations.textile
+++ b/guides/source/migrations.textile
@@ -111,6 +111,7 @@ Active Record provides methods that perform common data definition tasks in a
database independent way (you'll read about them in detail later):
* +add_column+
+* +add_reference+
* +add_index+
* +change_column+
* +change_table+
@@ -120,6 +121,7 @@ database independent way (you'll read about them in detail later):
* +remove_column+
* +remove_index+
* +rename_column+
+* +remove_reference+
If you need to perform tasks specific to your database (for example create a
"foreign key":#active-record-and-referential-integrity constraint) then the
@@ -332,6 +334,51 @@ NOTE: The generated migration file for destructive migrations will still be
old-style using the +up+ and +down+ methods. This is because Rails needs to know
the original data types defined when you made the original changes.
+Also the generator accepts column type as +references+(also available as +belongs_to+), for instance
+
+<shell>
+$ rails generate migration AddUserRefToProducts user:references
+</shell>
+
+generates
+
+<ruby>
+class AddUserRefToProducts < ActiveRecord::Migration
+ def change
+ add_reference :products, :user, :index => true
+ end
+end
+</ruby>
+
+This migration will create a user_id column and appropriate index.
+
+h4. Supported type modifiers
+
+You can also specify some options just after the field type between curly braces. You can use the
+following modifiers:
+
+* +limit+ Sets the maximum size of the +string/text/binary/integer+ fields
+* +precision+ Defines the precision for the +decimal+ fields
+* +scale+ Defines the scale for the +decimal+ fields
+* +polymorphic+ Adds a +type+ column for +belongs_to+ associations
+
+For instance running
+
+<shell>
+$ rails generate migration AddDetailsToProducts price:decimal{5,2} supplier:references{polymorphic}
+</shell>
+
+will produce a migration that looks like this
+
+<ruby>
+class AddDetailsToProducts < ActiveRecord::Migration
+ def change
+ add_column :products, :price, :precision => 5, :scale => 2
+ add_reference :products, :user, :polymorphic => true, :index => true
+ end
+end
+</ruby>
+
h3. Writing a Migration
Once you have created your migration using one of the generators it's time to
diff --git a/guides/source/plugins.textile b/guides/source/plugins.textile
index 95e38db483..9001857a5f 100644
--- a/guides/source/plugins.textile
+++ b/guides/source/plugins.textile
@@ -427,4 +427,4 @@ h4. References
* "Developing a RubyGem using Bundler":https://github.com/radar/guides/blob/master/gem-development.md
* "Using Gemspecs As Intended":http://yehudakatz.com/2010/04/02/using-gemspecs-as-intended/
* "Gemspec Reference":http://docs.rubygems.org/read/chapter/20
-* "GemPlugins":http://www.mbleigh.com/2008/06/11/gemplugins-a-brief-introduction-to-the-future-of-rails-plugins
+* "GemPlugins":http://www.intridea.com/blog/2008/6/11/gemplugins-a-brief-introduction-to-the-future-of-rails-plugins
diff --git a/guides/source/security.textile b/guides/source/security.textile
index 626d6fa508..8879122b66 100644
--- a/guides/source/security.textile
+++ b/guides/source/security.textile
@@ -851,7 +851,7 @@ Network traffic is mostly based on the limited Western alphabet, so new characte
&amp;#108;&amp;#101;&amp;#114;&amp;#116;&amp;#40;&amp;#39;&amp;#88;&amp;#83;&amp;#83;&amp;#39;&amp;#41;>
</html>
-This example pops up a message box. It will be recognized by the above sanitize() filter, though. A great tool to obfuscate and encode strings, and thus “get to know your enemy”, is the "Hackvertor":http://www.businessinfo.co.uk/labs/hackvertor/hackvertor.php. Rails' sanitize() method does a good job to fend off encoding attacks.
+This example pops up a message box. It will be recognized by the above sanitize() filter, though. A great tool to obfuscate and encode strings, and thus “get to know your enemy”, is the "Hackvertor":https://hackvertor.co.uk/public. Rails' sanitize() method does a good job to fend off encoding attacks.
h5. Examples from the Underground
diff --git a/guides/source/testing.textile b/guides/source/testing.textile
index d35be6a70e..4faf59fad8 100644
--- a/guides/source/testing.textile
+++ b/guides/source/testing.textile
@@ -1,62 +1,57 @@
h2. A Guide to Testing Rails Applications
-This guide covers built-in mechanisms offered by Rails to test your application. By referring to this guide, you will be able to:
+This guide covers built-in mechanisms offered by Rails to test your
+application. By referring to this guide, you will be able to:
* Understand Rails testing terminology
-* Write unit, functional and integration tests for your application
+* Write unit, functional, and integration tests for your application
* Identify other popular testing approaches and plugins
-This guide won't teach you to write a Rails application; it assumes basic familiarity with the Rails way of doing things.
-
endprologue.
h3. Why Write Tests for your Rails Applications?
-* Rails makes it super easy to write your tests. It starts by producing skeleton test code in the background while you are creating your models and controllers.
-* By simply running your Rails tests you can ensure your code adheres to the desired functionality even after some major code refactoring.
-* Rails tests can also simulate browser requests and thus you can test your application's response without having to test it through your browser.
-
-h3. Introduction to Testing
-
-Testing support was woven into the Rails fabric from the beginning. It wasn't an "oh! let's bolt on support for running tests because they're new and cool" epiphany. Just about every Rails application interacts heavily with a database - and, as a result, your tests will need a database to interact with as well. To write efficient tests, you'll need to understand how to set up this database and populate it with sample data.
+Rails makes it super easy to write your tests. It starts by producing skeleton test code while you are creating your models and controllers.
-h4. The Three Environments
+By simply running your Rails tests you can ensure your code adheres to the desired functionality even after some major code refactoring.
-Every Rails application you build has 3 sides: a side for production, a side for development, and a side for testing.
+Rails tests can also simulate browser requests and thus you can test your application's response without having to test it through your browser.
-One place you'll find this distinction is in the +config/database.yml+ file. This YAML configuration file has 3 different sections defining 3 unique database setups:
+h3. Introduction to Testing
-* production
-* development
-* test
+Testing support was woven into the Rails fabric from the beginning. It wasn't an "oh! let's bolt on support for running tests because they're new and cool" epiphany. Just about every Rails application interacts heavily with a database and, as a result, your tests will need a database to interact with as well. To write efficient tests, you'll need to understand how to set up this database and populate it with sample data.
-This allows you to set up and interact with test data without any danger of your tests altering data from your production environment.
+h4. The Test Environment
-For example, suppose you need to test your new +delete_this_user_and_every_everything_associated_with_it+ function. Wouldn't you want to run this in an environment where it makes no difference if you destroy data or not?
+By default, every Rails application has three environments: development, test, and production. The database for each one of them is configured in +config/database.yml+.
-When you do end up destroying your testing database (and it will happen, trust me), you can rebuild it from scratch according to the specs defined in the development database. You can do this by running +rake db:test:prepare+.
+A dedicated test database allows you to set up and interact with test data in isolation. Tests can mangle test data with confidence, that won't touch the data in the development or production databases.
h4. Rails Sets up for Testing from the Word Go
Rails creates a +test+ folder for you as soon as you create a Rails project using +rails new+ _application_name_. If you list the contents of this folder then you shall see:
<shell>
-$ ls -F test/
+$ ls -F test
-fixtures/ functional/ integration/ test_helper.rb unit/
+fixtures/ functional/ integration/ performance/ test_helper.rb unit/
</shell>
-The +unit+ folder is meant to hold tests for your models, the +functional+ folder is meant to hold tests for your controllers, and the +integration+ folder is meant to hold tests that involve any number of controllers interacting. Fixtures are a way of organizing test data; they reside in the +fixtures+ folder. The +test_helper.rb+ file holds the default configuration for your tests.
+The +unit+ directory is meant to hold tests for your models, the +functional+ directory is meant to hold tests for your controllers, the +integration+ directory is meant to hold tests that involve any number of controllers interacting, and the +performance+ directory is meant for performance tests.
+
+Fixtures are a way of organizing test data; they reside in the +fixtures+ folder.
+
+The +test_helper.rb+ file holds the default configuration for your tests.
h4. The Low-Down on Fixtures
For good tests, you'll need to give some thought to setting up test data. In Rails, you can handle this by defining and customizing fixtures.
-h5. What are Fixtures?
+h5. What Are Fixtures?
-_Fixtures_ is a fancy word for sample data. Fixtures allow you to populate your testing database with predefined data before your tests run. Fixtures are database independent and assume a single format: *YAML*.
+_Fixtures_ is a fancy word for sample data. Fixtures allow you to populate your testing database with predefined data before your tests run. Fixtures are database independent written in YAML. There is one file per model.
-You'll find fixtures under your +test/fixtures+ directory. When you run +rails generate model+ to create a new model, fixture stubs will be automatically created and placed in this directory.
+You'll find fixtures under your +test/fixtures+ directory. When you run +rails generate model+ to create a new model fixture stubs will be automatically created and placed in this directory.
h5. YAML
@@ -77,35 +72,20 @@ steve:
profession: guy with keyboard
</yaml>
-Each fixture is given a name followed by an indented list of colon-separated key/value pairs. Records are separated by a blank space. You can place comments in a fixture file by using the # character in the first column.
+Each fixture is given a name followed by an indented list of colon-separated key/value pairs. Records are typically separated by a blank space. You can place comments in a fixture file by using the # character in the first column.
h5. ERB'in It Up
-ERB allows you to embed ruby code within templates. YAML fixture format is pre-processed with ERB when you load fixtures. This allows you to use Ruby to help you generate some sample data.
-
-<erb>
-<% earth_size = 20 %>
-mercury:
- size: <%= earth_size / 50 %>
- brightest_on: <%= 113.days.ago.to_s(:db) %>
-
-venus:
- size: <%= earth_size / 2 %>
- brightest_on: <%= 67.days.ago.to_s(:db) %>
-
-mars:
- size: <%= earth_size - 69 %>
- brightest_on: <%= 13.days.from_now.to_s(:db) %>
-</erb>
-
-Anything encased within the
+ERB allows you to embed Ruby code within templates. The YAML fixture format is pre-processed with ERB when Rails loads fixtures. This allows you to use Ruby to help you generate some sample data. For example, the following code generates a thousand users:
<erb>
-<% %>
+<% 1000.times do |n| %>
+user_<%= n %>:
+ username: <%= "user%03d" % n %>
+ email: <%= "user%03d@example.com" % n %>
+<% end %>
</erb>
-tag is considered Ruby code. When this fixture is loaded, the +size+ attribute of the three records will be set to 20/50, 20/2, and 20-69 respectively. The +brightest_on+ attribute will also be evaluated and formatted by Rails to be compatible with the database.
-
h5. Fixtures in Action
Rails by default automatically loads all fixtures from the +test/fixtures+ folder for your unit and functional test. Loading involves three steps:
@@ -377,12 +357,12 @@ There are a bunch of different types of assertions you can use. Here's the compl
|_.Assertion |_.Purpose|
|+assert( boolean, [msg] )+ |Ensures that the object/expression is true.|
-|+assert_equal( obj1, obj2, [msg] )+ |Ensures that +obj1 == obj2+ is true.|
-|+assert_not_equal( obj1, obj2, [msg] )+ |Ensures that +obj1 == obj2+ is false.|
-|+assert_same( obj1, obj2, [msg] )+ |Ensures that +obj1.equal?(obj2)+ is true.|
-|+assert_not_same( obj1, obj2, [msg] )+ |Ensures that +obj1.equal?(obj2)+ is false.|
+|+assert_equal( expected, actual, [msg] )+ |Ensures that +expected == actual+ is true.|
+|+assert_not_equal( expected, actual, [msg] )+ |Ensures that +expected != actual+ is true.|
+|+assert_same( expected, actual, [msg] )+ |Ensures that +expected.equal?(actual)+ is true.|
+|+assert_not_same( expected, actual, [msg] )+ |Ensures that +!expected.equal?(actual)+ is true.|
|+assert_nil( obj, [msg] )+ |Ensures that +obj.nil?+ is true.|
-|+assert_not_nil( obj, [msg] )+ |Ensures that +obj.nil?+ is false.|
+|+assert_not_nil( obj, [msg] )+ |Ensures that +!obj.nil?+ is true.|
|+assert_match( regexp, string, [msg] )+ |Ensures that a string matches the regular expression.|
|+assert_no_match( regexp, string, [msg] )+ |Ensures that a string doesn't match the regular expression.|
|+assert_in_delta( expecting, actual, delta, [msg] )+ |Ensures that the numbers +expecting+ and +actual+ are within +delta+ of each other.|
@@ -526,7 +506,7 @@ You also have access to three instance variables in your functional tests:
h4. Testing Templates and Layouts
-If you want to make sure that the response rendered the correct template and layout, you can use the +assert_template+
+If you want to make sure that the response rendered the correct template and layout, you can use the +assert_template+
method:
<ruby>