diff options
Diffstat (limited to 'guides')
24 files changed, 501 insertions, 177 deletions
diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md index cd3fa9f65b..dd5ca4b395 100644 --- a/guides/CHANGELOG.md +++ b/guides/CHANGELOG.md @@ -1,5 +1,13 @@ +* New section in Active Record Association Basics: Single Table Inheritance + + *Andrey Nering* + * New section in Active Record Querying: Understanding The Method Chaining *Andrey Nering* +* New section in Configuring: Search Engines Indexing + + *Andrey Nering* + Please check [4-2-stable](https://github.com/rails/rails/blob/4-2-stable/guides/CHANGELOG.md) for previous changes. diff --git a/guides/assets/images/favicon.ico b/guides/assets/images/favicon.ico Binary files differindex e0e80cf8f1..faa10b4580 100644 --- a/guides/assets/images/favicon.ico +++ b/guides/assets/images/favicon.ico diff --git a/guides/bug_report_templates/action_controller_gem.rb b/guides/bug_report_templates/action_controller_gem.rb index e04d79c818..032e6bfe11 100644 --- a/guides/bug_report_templates/action_controller_gem.rb +++ b/guides/bug_report_templates/action_controller_gem.rb @@ -2,6 +2,7 @@ gem 'rails', '4.2.0' require 'rails' +require 'rack/test' require 'action_controller/railtie' class TestApp < Rails::Application @@ -27,7 +28,6 @@ class TestController < ActionController::Base end require 'minitest/autorun' -require 'rack/test' # Ensure backward compatibility with Minitest 4 Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test) diff --git a/guides/source/action_controller_overview.md b/guides/source/action_controller_overview.md index 80000baf66..f68179841e 100644 --- a/guides/source/action_controller_overview.md +++ b/guides/source/action_controller_overview.md @@ -737,7 +737,7 @@ You can choose not to yield and build the response yourself, in which case the a While the most common way to use filters is by creating private methods and using *_action to add them, there are two other ways to do the same thing. -The first is to use a block directly with the *_action methods. The block receives the controller as an argument, and the `require_login` filter from above could be rewritten to use a block: +The first is to use a block directly with the *\_action methods. The block receives the controller as an argument, and the `require_login` filter from above could be rewritten to use a block: ```ruby class ApplicationController < ActionController::Base diff --git a/guides/source/action_mailer_basics.md b/guides/source/action_mailer_basics.md index e55ff16495..73b240ff2c 100644 --- a/guides/source/action_mailer_basics.md +++ b/guides/source/action_mailer_basics.md @@ -442,6 +442,39 @@ end Will render the HTML part using the `my_layout.html.erb` file and the text part with the usual `user_mailer.text.erb` file if it exists. +### Previewing Emails + +Action Mailer previews provide a way to see how emails look by visiting a +special URL that renders them. In the above example, the preview class for +`UserMailer` should be named `UserMailerPreview` and located in +`test/mailers/previews/user_mailer_preview.rb`. To see the preview of +`welcome_email`, implement a method that has the same name and call +`UserMailer.welcome_email`: + +```ruby +class UserMailerPreview < ActionMailer::Preview + def welcome_email + UserMailer.welcome_email(User.first) + end +end +``` + +Then the preview will be available in <http://localhost:3000/rails/mailers/user_mailer/welcome_email>. + +If you change something in `app/views/user_mailer/welcome_email.html.erb` +or the mailer itself, it'll automatically reload and render it so you can +visually see the new style instantly. A list of previews are also available +in <http://localhost:3000/rails/mailers>. + +By default, these preview classes live in `test/mailers/previews`. +This can be configured using the `preview_path` option. For example, if you +want to change it to `lib/mailer_previews`, you can configure it in +`config/application.rb`: + +```ruby +config.action_mailer.preview_path = "#{Rails.root}/lib/mailer_previews" +``` + ### Generating URLs in Action Mailer Views Unlike controllers, the mailer instance doesn't have any context about the diff --git a/guides/source/action_view_overview.md b/guides/source/action_view_overview.md index 665a2b71ff..8f6676dc65 100644 --- a/guides/source/action_view_overview.md +++ b/guides/source/action_view_overview.md @@ -190,6 +190,22 @@ One way to use partials is to treat them as the equivalent of subroutines; a way Here, the `_ad_banner.html.erb` and `_footer.html.erb` 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. +#### `render` without `partial` and `locals` options + +In the above example, `render` takes 2 options: `partial` and `locals`. But if +these are the only options you want to pass, you can skip using these options. +For example, instead of: + +```erb +<%= render partial: "product", locals: {product: @product} %> +``` + +You can also do: + +```erb +<%= render "product", product: @product %> +``` + #### The `as` and `object` options By default `ActionView::Partials::PartialRenderer` has its object in a local variable with the same name as the template. So, given: @@ -349,83 +365,6 @@ WIP: Not all the helpers are listed here. For a full list see the [API documenta The following is only a brief overview summary of the helpers available in Action View. It's recommended that you review the [API Documentation](http://api.rubyonrails.org/classes/ActionView/Helpers.html), which covers all of the helpers in more detail, but this should serve as a good starting point. -### RecordTagHelper - -This module provides methods for generating container tags, such as `div`, for your record. This is the recommended way of creating a container for render your Active Record object, as it adds an appropriate class and id attributes to that container. You can then refer to those containers easily by following the convention, instead of having to think about which class or id attribute you should use. - -#### content_tag_for - -Renders a container tag that relates to your Active Record Object. - -For example, given `@article` is the object of `Article` class, you can do: - -```html+erb -<%= content_tag_for(:tr, @article) do %> - <td><%= @article.title %></td> -<% end %> -``` - -This will generate this HTML output: - -```html -<tr id="article_1234" class="article"> - <td>Hello World!</td> -</tr> -``` - -You can also supply HTML attributes as an additional option hash. For example: - -```html+erb -<%= content_tag_for(:tr, @article, class: "frontpage") do %> - <td><%= @article.title %></td> -<% end %> -``` - -Will generate this HTML output: - -```html -<tr id="article_1234" class="article frontpage"> - <td>Hello World!</td> -</tr> -``` - -You can pass a collection of Active Record objects. This method will loop through your objects and create a container for each of them. For example, given `@articles` is an array of two `Article` objects: - -```html+erb -<%= content_tag_for(:tr, @articles) do |article| %> - <td><%= article.title %></td> -<% end %> -``` - -Will generate this HTML output: - -```html -<tr id="article_1234" class="article"> - <td>Hello World!</td> -</tr> -<tr id="article_1235" class="article"> - <td>Ruby on Rails Rocks!</td> -</tr> -``` - -#### div_for - -This is actually a convenient method which calls `content_tag_for` internally with `:div` as the tag name. You can pass either an Active Record object or a collection of objects. For example: - -```html+erb -<%= div_for(@article, class: "frontpage") do %> - <td><%= @article.title %></td> -<% end %> -``` - -Will generate this HTML output: - -```html -<div id="article_1234" class="article frontpage"> - <td>Hello World!</td> -</div> -``` - ### AssetTagHelper This module provides methods for generating HTML that links views to assets such as images, JavaScript files, stylesheets, and feeds. @@ -1601,7 +1540,7 @@ details can be found in the [Rails Security Guide](security.html#cross-site-requ Localized Views --------------- -Action View has the ability render different templates depending on the current locale. +Action View has the ability to render different templates depending on the current locale. For example, suppose you have a `ArticlesController` with a show action. By default, calling this action will render `app/views/articles/show.html.erb`. But if you set `I18n.locale = :de`, then `app/views/articles/show.de.html.erb` will be rendered instead. If the localized template isn't present, the undecorated version will be used. This means you're not required to provide localized views for all cases, but they will be preferred and used if available. diff --git a/guides/source/active_job_basics.md b/guides/source/active_job_basics.md index 4d1625b28d..953c29719d 100644 --- a/guides/source/active_job_basics.md +++ b/guides/source/active_job_basics.md @@ -205,7 +205,7 @@ class ProcessVideoJob < ActiveJob::Base end def perform(video) - # do process video + # Do process video end end @@ -238,13 +238,13 @@ class GuestsCleanupJob < ActiveJob::Base queue_as :default before_enqueue do |job| - # do something with the job instance + # Do something with the job instance end around_perform do |job, block| - # do something before perform + # Do something before perform block.call - # do something after perform + # Do something after perform end def perform @@ -311,7 +311,7 @@ class GuestsCleanupJob < ActiveJob::Base queue_as :default rescue_from(ActiveRecord::RecordNotFound) do |exception| - # do something with the exception + # Do something with the exception end def perform diff --git a/guides/source/active_record_migrations.md b/guides/source/active_record_migrations.md index 97cabc1728..b8db21a989 100644 --- a/guides/source/active_record_migrations.md +++ b/guides/source/active_record_migrations.md @@ -479,7 +479,8 @@ Rails will generate a name for every foreign key starting with There is a `:name` option to specify a different name if needed. NOTE: Active Record only supports single column foreign keys. `execute` and -`structure.sql` are required to use composite foreign keys. +`structure.sql` are required to use composite foreign keys. See +[Schema Dumping and You](#schema-dumping-and-you). Removing a foreign key is easy as well: @@ -695,6 +696,10 @@ of `create_table` and `reversible`, replacing `create_table` by `drop_table`, and finally replacing `up` by `down` and vice-versa. This is all taken care of by `revert`. +NOTE: If you want to add check constraints like in the examples above, +you will have to use `structure.sql` as dump method. See +[Schema Dumping and You](#schema-dumping-and-you). + Running Migrations ------------------ @@ -943,10 +948,10 @@ that Active Record supports. This could be very useful if you were to distribute an application that is able to run against multiple databases. There is however a trade-off: `db/schema.rb` cannot express database specific -items such as 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 `:sql`. +items such as triggers, stored procedures or check constraints. 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 `:sql`. Instead of using Active Record's schema dumper, the database's structure will be dumped using a tool specific to the database (via the `db:structure:dump` diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md index 373a98bb85..ad5103da69 100644 --- a/guides/source/active_record_querying.md +++ b/guides/source/active_record_querying.md @@ -317,7 +317,7 @@ end The `find_each` method accepts most of the options allowed by the regular `find` method, except for `:order` and `:limit`, which are reserved for internal use by `find_each`. -Two additional options, `:batch_size` and `:start`, are available as well. +Two additional options, `:batch_size` and `:begin_at`, are available as well. **`:batch_size`** @@ -329,19 +329,32 @@ User.find_each(batch_size: 5000) do |user| end ``` -**`:start`** +**`:begin_at`** -By default, records are fetched in ascending order of the primary key, which must be an integer. The `:start` option allows you to configure the first ID of the sequence whenever the lowest ID is not the one you need. This would be useful, for example, if you wanted to resume an interrupted batch process, provided you saved the last processed ID as a checkpoint. +By default, records are fetched in ascending order of the primary key, which must be an integer. The `:begin_at` option allows you to configure the first ID of the sequence whenever the lowest ID is not the one you need. This would be useful, for example, if you wanted to resume an interrupted batch process, provided you saved the last processed ID as a checkpoint. For example, to send newsletters only to users with the primary key starting from 2000, and to retrieve them in batches of 5000: ```ruby -User.find_each(start: 2000, batch_size: 5000) do |user| +User.find_each(begin_at: 2000, batch_size: 5000) do |user| NewsMailer.weekly(user).deliver_now end ``` -Another example would be if you wanted multiple workers handling the same processing queue. You could have each worker handle 10000 records by setting the appropriate `:start` option on each worker. +Another example would be if you wanted multiple workers handling the same processing queue. You could have each worker handle 10000 records by setting the appropriate `:begin_at` option on each worker. + +**`:end_at`** + +Similar to the `:begin_at` option, `:end_at` allows you to configure the last ID of the sequence whenever the highest ID is not the one you need. +This would be useful, for example, if you wanted to run a batch process, using a subset of records based on `:begin_at` and `:end_at` + +For example, to send newsletters only to users with the primary key starting from 2000 upto 10000 and to retrieve them in batches of 1000: + +```ruby +User.find_each(begin_at: 2000, end_at: 10000, batch_size: 5000) do |user| + NewsMailer.weekly(user).deliver_now +end +``` #### `find_in_batches` @@ -356,7 +369,7 @@ end ##### Options for `find_in_batches` -The `find_in_batches` method accepts the same `:batch_size` and `:start` options as `find_each`. +The `find_in_batches` method accepts the same `:batch_size`, `:begin_at` and `:end_at` options as `find_each`. Conditions ---------- diff --git a/guides/source/active_record_validations.md b/guides/source/active_record_validations.md index c9af70934a..31c5b07a05 100644 --- a/guides/source/active_record_validations.md +++ b/guides/source/active_record_validations.md @@ -227,8 +227,26 @@ end ``` We'll cover validation errors in greater depth in the [Working with Validation -Errors](#working-with-validation-errors) section. For now, let's turn to the -built-in validation helpers that Rails provides by default. +Errors](#working-with-validation-errors) section. + +### `errors.details` + +To check which validations failed on an invalid attribute, you can use +`errors.details[:attribute]`. It returns an array of hashes with an `:error` +key to get the symbol of the validator: + +```ruby +class Person < ActiveRecord::Base + validates :name, presence: true +end + +>> person = Person.new +>> person.valid? +>> person.errors.details[:name] #=> [{error: :blank}] +``` + +Using `details` with custom validators is covered in the [Working with +Validation Errors](#working-with-validation-errors) section. Validation Helpers ------------------ @@ -452,7 +470,7 @@ point number. To specify that only integral numbers are allowed set If you set `:only_integer` to `true`, then it will use the ```ruby -/\A[+-]?\d+\Z/ +/\A[+-]?\d+\z/ ``` regular expression to validate the attribute's value. Otherwise, it will try to @@ -588,9 +606,7 @@ This helper validates that the attribute's value is unique right before the object gets saved. It does not create a uniqueness constraint in the database, so it may happen that two different database connections create two records with the same value for a column that you intend to be unique. To avoid that, -you must create a unique index on both columns in your database. See -[the MySQL manual](http://dev.mysql.com/doc/refman/5.6/en/multiple-column-indexes.html) -for more details about multiple column indexes. +you must create a unique index on that column in your database. ```ruby class Account < ActiveRecord::Base @@ -610,6 +626,7 @@ class Holiday < ActiveRecord::Base message: "should happen once per year" } end ``` +Should you wish to create a database constraint to prevent possible violations of a uniqueness validation using the `:scope` option, you must create a unique index on both columns in your database. See [the MySQL manual](http://dev.mysql.com/doc/refman/5.6/en/multiple-column-indexes.html) for more details about multiple column indexes or [the PostgreSQL manual](http://www.postgresql.org/docs/9.4/static/ddl-constraints.html) for examples of unique constraints that refer to a group of columns. There is also a `:case_sensitive` option that you can use to define whether the uniqueness constraint will be case sensitive or not. This option defaults to @@ -1061,7 +1078,7 @@ Another way to do this is using `[]=` setter ```ruby class Person < ActiveRecord::Base def a_method_used_for_validation_purposes - errors[:name] = "cannot contain the characters !@#%*()_-+=" + errors.messages[:name] << "cannot contain the characters !@#%*()_-+=" end end @@ -1074,6 +1091,43 @@ Another way to do this is using `[]=` setter # => ["Name cannot contain the characters !@#%*()_-+="] ``` +### `errors.details` + +You can specify a validator type to the returned error details hash using the +`errors.add` method. + +```ruby +class Person < ActiveRecord::Base + def a_method_used_for_validation_purposes + errors.add(:name, :invalid_characters) + end +end + +person = Person.create(name: "!@#") + +person.errors.details[:name] +# => [{error: :invalid_characters}] +``` + +To improve the error details to contain the unallowed characters set for instance, +you can pass additional keys to `errors.add`. + +```ruby +class Person < ActiveRecord::Base + def a_method_used_for_validation_purposes + errors.add(:name, :invalid_characters, not_allowed: "!@#%*()_-+=") + end +end + +person = Person.create(name: "!@#") + +person.errors.details[:name] +# => [{error: :invalid_characters, not_allowed: "!@#%*()_-+="}] +``` + +All built in Rails validators populate the details hash with the corresponding +validator type. + ### `errors[:base]` You can add error messages that are related to the object's state as a whole, instead of being related to a specific attribute. You can use this method when you want to say that the object is invalid, no matter the values of its attributes. Since `errors[:base]` is an array, you can simply add a string to it and it will be used as an error message. diff --git a/guides/source/association_basics.md b/guides/source/association_basics.md index dab885a8fb..cd715aba1f 100644 --- a/guides/source/association_basics.md +++ b/guides/source/association_basics.md @@ -171,7 +171,7 @@ class CreateCustomers < ActiveRecord::Migration end create_table :orders do |t| - t.belongs_to :customer, index:true + t.belongs_to :customer, index: true t.datetime :order_date t.timestamps null: false end @@ -691,7 +691,7 @@ c.first_name = 'Manny' c.first_name == o.customer.first_name # => false ``` -This happens because c and o.customer are two different in-memory representations of the same data, and neither one is automatically refreshed from changes to the other. Active Record provides the `:inverse_of` option so that you can inform it of these relations: +This happens because `c` and `o.customer` are two different in-memory representations of the same data, and neither one is automatically refreshed from changes to the other. Active Record provides the `:inverse_of` option so that you can inform it of these relations: ```ruby class Customer < ActiveRecord::Base @@ -726,10 +726,10 @@ Most associations with standard names will be supported. However, associations that contain the following options will not have their inverses set automatically: -* :conditions -* :through -* :polymorphic -* :foreign_key +* `:conditions` +* `:through` +* `:polymorphic` +* `:foreign_key` Detailed Association Reference ------------------------------ @@ -1986,8 +1986,8 @@ While Rails uses intelligent defaults that will work well in most situations, th ```ruby class Parts < ActiveRecord::Base - has_and_belongs_to_many :assemblies, autosave: true, - readonly: true + has_and_belongs_to_many :assemblies, -> { readonly }, + autosave: true end ``` @@ -1999,7 +1999,6 @@ The `has_and_belongs_to_many` association supports these options: * `:foreign_key` * `:join_table` * `:validate` -* `:readonly` ##### `:association_foreign_key` @@ -2243,3 +2242,67 @@ Extensions can refer to the internals of the association proxy using these three * `proxy_association.owner` returns the object that the association is a part of. * `proxy_association.reflection` returns the reflection object that describes the association. * `proxy_association.target` returns the associated object for `belongs_to` or `has_one`, or the collection of associated objects for `has_many` or `has_and_belongs_to_many`. + +Single Table Inheritance +------------------------ + +Sometimes, you may want to share fields and behavior between different models. +Let's say we have Car, Motorcycle and Bicycle models. We will want to share +the `color` and `price` fields and some methods for all of them, but having some +specific behavior for each, and separated controllers too. + +Rails makes this quite easy. First, let's generate the base Vehicle model: + +```bash +$ rails generate model vehicle type:string color:string price:decimal{10.2} +``` + +Did you note we are adding a "type" field? Since all models will be saved in a +single database table, Rails will save in this column the name of the model that +is being saved. In our example, this can be "Car", "Motorcycle" or "Bicycle." +STI won't work without a "type" field in the table. + +Next, we will generate the three models that inherit from Vehicle. For this, +we can use the `--parent=PARENT` option, which will generate a model that +inherits from the specified parent and without equivalent migration (since the +table already exists). + +For example, to generate the Car model: + +```bash +$ rails generate model car --parent=Vehicle +``` + +The generated model will look like this: + +```ruby +class Car < Vehicle +end +``` + +This means that all behavior added to Vehicle is available for Car too, as +associations, public methods, etc. + +Creating a car will save it in the `vehicles` table with "Car" as the `type` field: + +```ruby +Car.create color: 'Red', price: 10000 +``` + +will generate the following SQL: + +```sql +INSERT INTO "vehicles" ("type", "color", "price") VALUES ("Car", "Red", 10000) +``` + +Querying car records will just search for vehicles that are cars: + +```ruby +Car.all +``` + +will run a query like: + +```sql +SELECT "vehicles".* FROM "vehicles" WHERE "vehicles"."type" IN ('Car') +``` diff --git a/guides/source/autoloading_and_reloading_constants.md b/guides/source/autoloading_and_reloading_constants.md index c4fac1cff5..9e78eebf82 100644 --- a/guides/source/autoloading_and_reloading_constants.md +++ b/guides/source/autoloading_and_reloading_constants.md @@ -114,6 +114,16 @@ certain nesting does not necessarily correlate with the namespaces at the spot. Even more, they are totally independent, take for instance ```ruby +module X + module Y + end +end + +module A + module B + end +end + module X::Y module A::B # (3) @@ -141,9 +151,10 @@ executed, and popped after it. * A singleton class opened with `class << object` gets pushed, and popped later. -* When any of the `*_eval` family of methods is called using a string argument, +* When `instance_eval` is called using a string argument, the singleton class of the receiver is pushed to the nesting of the eval'ed -code. +code. When `class_eval` or `module_eval` is called using a string argument, +the receiver is pushed to the nesting of the eval'ed code. * The nesting at the top-level of code interpreted by `Kernel#load` is empty unless the `load` call receives a true value as second argument, in which case @@ -290,7 +301,9 @@ order. The ancestors of those elements are ignored. 2. If not found, then the algorithm walks up the ancestor chain of the cref. -3. If not found, `const_missing` is invoked on the cref. The default +3. If not found and the cref is a module, the constant is looked up in `Object`. + +4. If not found, `const_missing` is invoked on the cref. The default implementation of `const_missing` raises `NameError`, but it can be overridden. Rails autoloading **does not emulate this algorithm**, but its starting point is @@ -313,7 +326,7 @@ relative: `::Billing::Invoice`. That would force `Billing` to be looked up only as a top-level constant. `Invoice` on the other hand is qualified by `Billing` and we are going to see -its resolution next. Let's call *parent* to that qualifying class or module +its resolution next. Let's define *parent* to be that qualifying class or module object, that is, `Billing` in the example above. The algorithm for qualified constants goes like this: @@ -450,8 +463,9 @@ Also, this collection is configurable via `config.autoload_paths`. For example, by adding this to `config/application.rb`: ```ruby -config.autoload_paths += "#{Rails.root}/lib" +config.autoload_paths << "#{Rails.root}/lib" ``` +`config.autoload_paths` is accessible from environment-specific configuration files, but any changes made to it outside `config/application.rb` don't have an effect. The value of `autoload_paths` can be inspected. In a just generated application it is (edited): diff --git a/guides/source/command_line.md b/guides/source/command_line.md index 78f26ccefa..19ccdc5488 100644 --- a/guides/source/command_line.md +++ b/guides/source/command_line.md @@ -419,14 +419,6 @@ The most common tasks of the `db:` Rake namespace are `migrate` and `create`, an More information about migrations can be found in the [Migrations](migrations.html) guide. -### `doc` - -The `doc:` namespace has the tools to generate documentation for your app, API documentation, guides. Documentation can also be stripped which is mainly useful for slimming your codebase, like if you're writing a Rails application for an embedded platform. - -* `rake doc:app` generates documentation for your application in `doc/app`. -* `rake doc:guides` generates Rails guides in `doc/guides`. -* `rake doc:rails` generates API documentation for Rails in `doc/api`. - ### `notes` `rake notes` will search through your code for comments beginning with FIXME, OPTIMIZE or TODO. The search is done in files with extension `.builder`, `.rb`, `.rake`, `.yml`, `.yaml`, `.ruby`, `.css`, `.js` and `.erb` for both default and custom annotations. diff --git a/guides/source/configuring.md b/guides/source/configuring.md index 9c0f2ddc8a..994cc31cff 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -1049,3 +1049,21 @@ These configuration points are then available through the configuration object: Rails.configuration.x.super_debugger # => true Rails.configuration.x.super_debugger.not_set # => nil ``` + +Search Engines Indexing +----------------------- + +Sometimes, you may want to prevent some pages of your application be visible on search sites like Google, +Bing, Yahoo or Duck Duck Go. The robots that index these sites will first analyse the +`https://your-site.com/robots.txt` file to know what pages it is allowed to index. + +Rails creates this file for you on `/public` folder. By default, it allows search engines to index all +pages of your application. If you want to block indexing on all pages of you application, use this: + +``` +User-agent: * +Disallow: / +``` + +To block just specific pages, it's necessary to use a more complex syntax. Learn it on the +[official documentation](http://www.robotstxt.org/robotstxt.html). diff --git a/guides/source/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md index 7381521658..32d1e2c6e7 100644 --- a/guides/source/contributing_to_ruby_on_rails.md +++ b/guides/source/contributing_to_ruby_on_rails.md @@ -173,6 +173,14 @@ $ git checkout -b my_new_branch It doesn't matter much what name you use, because this branch will only exist on your local computer and your personal repository on GitHub. It won't be part of the Rails Git repository. +### Bundle install + +Install the required gems. + +```bash +$ bundle install +``` + ### Running an Application Against Your Local Branch In case you need a dummy Rails app to test changes, the `--dev` flag of `rails new` generates an application that uses your local branch: @@ -368,6 +376,10 @@ A CHANGELOG entry should summarize what was changed and should end with author's Your name can be added directly after the last word if you don't provide any code examples or don't need multiple paragraphs. Otherwise, it's best to make as a new paragraph. +### Updating the Gemfile.lock + +Some changes requires the dependencies to be upgraded. In these cases make sure you run `bundle update` to get the right version of the dependency and commit the `Gemfile.lock` file within your changes. + ### Sanity Check You should not be the only person who looks at the code before you submit it. diff --git a/guides/source/debugging_rails_applications.md b/guides/source/debugging_rails_applications.md index a788dd48ad..6113a61f4c 100644 --- a/guides/source/debugging_rails_applications.md +++ b/guides/source/debugging_rails_applications.md @@ -242,6 +242,58 @@ The contents of the block, and therefore the string interpolation, is only evaluated if debug is enabled. This performance savings is only really noticeable with large amounts of logging, but it's a good practice to employ. + +Debugging with the `web-console` gem +------------------------------------- + +The web console allows you to create an interactive ruby session in your browser. An interactive +console is launched automatically in case on an error but can also be launched for debugging purposes +by invoking `console` in a view or controller. + +For example in a view: + +```ruby +# new.html.erb +<%= console %> +``` + +Or in a controller: + +```ruby +# posts_controller.rb +class PostsController < ApplicationController + def new + console + @post = Post.new + end +end +``` +###config.web_console.whitelisted_ips + +By default the web console can only be accessed from localhost. `config.web_console.whitelisted_ips` +lets you control which IPs have access to the console. + +For example, to allow access from both localhost and 192.168.0.100: + +```ruby +# config/application.rb +class Application < Rails::Application + config.web_console.whitelisted_ips = %w( 127.0.0.1 192.168.0.100 ) +end +``` + +To allow access from an entire network: + +```ruby +# config/application.rb +class Application < Rails::Application + config.web_console.whitelisted_ips = %w( 127.0.0.1 192.168.0.0/16 ) +end +``` + +Web console is a powerful tool so be careful who you open access to. + + Debugging with the `byebug` gem --------------------------------- @@ -544,7 +596,7 @@ This way an irb session will be started within the context you invoked it. But be warned: this is an experimental feature. The `var` method is the most convenient way to show variables and their values. -Let's let `byebug` to help us with it. +Let's let `byebug` help us with it. ``` (byebug) help var @@ -832,7 +884,7 @@ application. Here is a list of useful plugins for debugging: * [Footnotes](https://github.com/josevalim/rails-footnotes) Every Rails page has footnotes that give request information and link back to your source via TextMate. -* [Query Trace](https://github.com/ntalbott/query_trace/tree/master) Adds query +* [Query Trace](https://github.com/ruckus/active-record-query-trace/tree/master) Adds query origin tracing to your logs. * [Query Reviewer](https://github.com/nesquena/query_reviewer) This rails plugin not only runs "EXPLAIN" before each of your select queries in development, but diff --git a/guides/source/documents.yaml b/guides/source/documents.yaml index 67032a31f5..7ae3640937 100644 --- a/guides/source/documents.yaml +++ b/guides/source/documents.yaml @@ -33,7 +33,7 @@ url: active_record_querying.html description: This guide covers the database query interface provided by Active Record. - - name: Active Model basics + name: Active Model Basics url: active_model_basics.html description: This guide covers the use of model classes without Active Record. work_in_progress: true diff --git a/guides/source/form_helpers.md b/guides/source/form_helpers.md index 4c02c99cc7..90004c611b 100644 --- a/guides/source/form_helpers.md +++ b/guides/source/form_helpers.md @@ -687,7 +687,14 @@ class LabellingFormBuilder < ActionView::Helpers::FormBuilder end ``` -If you reuse this frequently you could define a `labeled_form_for` helper that automatically applies the `builder: LabellingFormBuilder` option. +If you reuse this frequently you could define a `labeled_form_for` helper that automatically applies the `builder: LabellingFormBuilder` option: + +```ruby +def labeled_form_for(record, options = {}, &block) + options.merge! builder: LabellingFormBuilder + form_for record, options, &block +end +``` The form builder used also determines what happens when you do diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md index 5945d48e98..51b8a2ca5f 100644 --- a/guides/source/getting_started.md +++ b/guides/source/getting_started.md @@ -193,6 +193,9 @@ following in the `blog` directory: $ bin/rails server ``` +TIP: If you are using Windows, you have to pass the scripts under the `bin` +folder directly to the Ruby interpreter e.g. `ruby bin\rails server`. + TIP: Compiling CoffeeScript and JavaScript asset compression requires you have a JavaScript runtime available on your system, in the absence of a runtime you will see an `execjs` error during asset compilation. @@ -908,6 +911,7 @@ And then finally, add the view for this action, located at <tr> <td><%= article.title %></td> <td><%= article.text %></td> + <td><%= link_to 'Show', article_path(article) %></td> </tr> <% end %> </table> @@ -2051,19 +2055,6 @@ resources: * The [Ruby on Rails mailing list](http://groups.google.com/group/rubyonrails-talk) * The [#rubyonrails](irc://irc.freenode.net/#rubyonrails) channel on irc.freenode.net -Rails also comes with built-in help that you can generate using the rake -command-line utility: - -* Running `rake doc:guides` will put a full copy of the Rails Guides in the - `doc/guides` folder of your application. Open `doc/guides/index.html` in your - web browser to explore the Guides. -* Running `rake doc:rails` will put a full copy of the API documentation for - Rails in the `doc/api` folder of your application. Open `doc/api/index.html` - in your web browser to explore the API documentation. - -TIP: To be able to generate the Rails Guides locally with the `doc:guides` rake -task you need to install the Redcarpet and Nokogiri gems. Add it to your `Gemfile` and run -`bundle install` and you're ready to go. Configuration Gotchas --------------------- diff --git a/guides/source/i18n.md b/guides/source/i18n.md index fd2051e675..4dc4c5a660 100644 --- a/guides/source/i18n.md +++ b/guides/source/i18n.md @@ -588,6 +588,26 @@ you can look up the `books.index.title` value **inside** `app/views/books/index. NOTE: Automatic translation scoping by partial is only available from the `translate` view helper method. +"Lazy" lookup can also be used in controllers: + +```yaml +en: + books: + create: + success: Book created! +``` + +This is useful for setting flash messages for instance: + +```ruby +class BooksController < ApplicationController + def create + # ... + redirect_to books_url, notice: t('.success') + end +end +``` + ### Interpolation In many cases you want to abstract your translations so that **variables can be interpolated into the translation**. For this reason the I18n API provides an interpolation feature. @@ -809,7 +829,7 @@ So, for example, instead of the default error message `"cannot be blank"` you co | validation | with option | message | interpolation | | ------------ | ------------------------- | ------------------------- | ------------- | -| confirmation | - | :confirmation | - | +| confirmation | - | :confirmation | attribute | | acceptance | - | :accepted | - | | presence | - | :blank | - | | absence | - | :present | - | @@ -829,6 +849,7 @@ So, for example, instead of the default error message `"cannot be blank"` you co | numericality | :equal_to | :equal_to | count | | numericality | :less_than | :less_than | count | | numericality | :less_than_or_equal_to | :less_than_or_equal_to | count | +| numericality | :other_than | :other_than | count | | numericality | :only_integer | :not_an_integer | - | | numericality | :odd | :odd | - | | numericality | :even | :even | - | @@ -1009,7 +1030,7 @@ In other contexts you might want to change this behavior, though. E.g. the defau module I18n class JustRaiseExceptionHandler < ExceptionHandler def call(exception, locale, key, options) - if exception.is_a?(MissingTranslation) + if exception.is_a?(MissingTranslationData) raise exception.to_exception else super @@ -1026,7 +1047,7 @@ This would re-raise only the `MissingTranslationData` exception, passing all oth However, if you are using `I18n::Backend::Pluralization` this handler will also raise `I18n::MissingTranslationData: translation missing: en.i18n.plural.rule` exception that should normally be ignored to fall back to the default pluralization rule for English locale. To avoid this you may use additional check for translation key: ```ruby -if exception.is_a?(MissingTranslation) && key.to_s != 'i18n.plural.rule' +if exception.is_a?(MissingTranslationData) && key.to_s != 'i18n.plural.rule' raise exception.to_exception else super diff --git a/guides/source/layouts_and_rendering.md b/guides/source/layouts_and_rendering.md index eb3c188d38..329d501ce0 100644 --- a/guides/source/layouts_and_rendering.md +++ b/guides/source/layouts_and_rendering.md @@ -316,12 +316,13 @@ NOTE: Unless overridden, your response returned from this render option will be #### Options for `render` -Calls to the `render` method generally accept four options: +Calls to the `render` method generally accept five options: * `:content_type` * `:layout` * `:location` * `:status` +* `:formats` ##### The `:content_type` Option @@ -430,6 +431,15 @@ Rails understands both numeric status codes and the corresponding symbols shown NOTE: If you try to render content along with a non-content status code (100-199, 204, 205 or 304), it will be dropped from the response. +##### The `:formats` Option + +Rails uses the format specified in request (or `:html` by default). You can change this adding the `:formats` option with a symbol or an array: + +```ruby +render formats: :xml +render formats: [:json, :xml] +``` + #### Finding Layouts To find the current layout, Rails first looks for a file in `app/views/layouts` with the same base name as the controller. For example, rendering actions from the `PhotosController` class will use `app/views/layouts/photos.html.erb` (or `app/views/layouts/photos.builder`). If there is no such controller-specific layout, Rails will use `app/views/layouts/application.html.erb` or `app/views/layouts/application.builder`. If there is no `.erb` layout, Rails will use a `.builder` layout if one exists. Rails also provides several ways to more precisely assign specific layouts to individual controllers and actions. @@ -1039,7 +1049,7 @@ As you already could see from the previous sections of this guide, `yield` is a <p> Name contains: <%= f.text_field :name_contains %> </p> - <%= end %> + <% end %> ``` * `roles/index.html.erb` @@ -1049,7 +1059,7 @@ As you already could see from the previous sections of this guide, `yield` is a <p> Title contains: <%= f.text_field :title_contains %> </p> - <%= end %> + <% end %> ``` * `shared/_search_filters.html.erb` @@ -1114,6 +1124,36 @@ You can also pass local variables into partials, making them even more powerful Although the same partial will be rendered into both views, Action View's submit helper will return "Create Zone" for the new action and "Update Zone" for the edit action. +To pass a local variable to a partial in only specific cases use the `local_assigns`. + +* `index.html.erb` + + ```erb + <%= render user.articles %> + ``` + +* `show.html.erb` + + ```erb + <%= render article, full: true %> + ``` + +* `_articles.html.erb` + + ```erb + <%= content_tag_for :article, article do |article| %> + <h2><%= article.title %></h2> + + <% if local_assigns[:full] %> + <%= simple_format article.body %> + <% else %> + <%= truncate article.body %> + <% end %> + <% end %> + ``` + +This way it is possible to use the partial without the need to declare all local variables. + Every partial also has a local variable with the same name as the partial (minus the underscore). You can pass an object in to this local variable via the `:object` option: ```erb diff --git a/guides/source/testing.md b/guides/source/testing.md index 94cfcf12b7..14bc75aa7d 100644 --- a/guides/source/testing.md +++ b/guides/source/testing.md @@ -120,9 +120,9 @@ user_<%= n %>: Rails by default automatically loads all fixtures from the `test/fixtures` directory for your models and controllers test. Loading involves three steps: -* Remove any existing data from the table corresponding to the fixture -* Load the fixture data into the table -* Dump the fixture data into a method in case you want to access it directly +1. Remove any existing data from the table corresponding to the fixture +2. Load the fixture data into the table +3. Dump the fixture data into a method in case you want to access it directly TIP: In order to remove existing data from the database, Rails tries to disable referential integrity triggers (like foreign keys and check constraints). If you are getting annoying permission errors on running tests, make sure the database user has privilege to disable these triggers in testing environment. (In PostgreSQL, only superusers can disable all triggers. Read more about PostgreSQL permissions [here](http://blog.endpoint.com/2012/10/postgres-system-triggers-error.html)) @@ -270,6 +270,8 @@ Finished tests in 0.009262s, 107.9680 tests/s, 107.9680 assertions/s. 1 tests, 1 assertions, 0 failures, 0 errors, 0 skips ``` +This will run all test methods from the test case. + You can also run a particular test method from the test case by running the test and providing the `test method name`. ```bash @@ -281,8 +283,6 @@ Finished tests in 0.009064s, 110.3266 tests/s, 110.3266 assertions/s. 1 tests, 1 assertions, 0 failures, 0 errors, 0 skips ``` -This will run all test methods from the test case. - The `.` (dot) above indicates a passing test. When a test fails you see an `F`; when a test throws an error you see an `E` in its place. The last line of the output is the summary. #### Your first failing test @@ -347,7 +347,11 @@ Finished tests in 0.047721s, 20.9551 tests/s, 20.9551 assertions/s. 1 tests, 1 assertions, 0 failures, 0 errors, 0 skips ``` -Now, if you noticed, we first wrote a test which fails for a desired functionality, then we wrote some code which adds the functionality and finally we ensured that our test passes. This approach to software development is referred to as _Test-Driven Development_ (TDD). +Now, if you noticed, we first wrote a test which fails for a desired +functionality, then we wrote some code which adds the functionality and finally +we ensured that our test passes. This approach to software development is +referred to as +[_Test-Driven Development_ (TDD)](http://c2.com/cgi/wiki?TestDrivenDevelopment). #### What an error looks like @@ -379,7 +383,11 @@ NameError: undefined local variable or method `some_undefined_variable' for #<Ar Notice the 'E' in the output. It denotes a test with error. -NOTE: The execution of each test method stops as soon as any error or an assertion failure is encountered, and the test suite continues with the next method. All test methods are executed in alphabetical order. +NOTE: The execution of each test method stops as soon as any error or an +assertion failure is encountered, and the test suite continues with the next +method. All test methods are executed in random order. The +[`config.active_support.test_order` option](http://edgeguides.rubyonrails.org/configuring.html#configuring-active-support) +can be used to configure test order. When a test fails you are presented with the corresponding backtrace. By default Rails filters that backtrace and will only print lines relevant to your @@ -480,21 +488,28 @@ In the `test_should_get_index` test, Rails simulates a request on the action cal The `get` method kicks off the web request and populates the results into the response. It accepts 4 arguments: -* The action of the controller you are requesting. This can be in the form of a string or a symbol. -* An optional hash of request parameters to pass into the action (eg. query string parameters or article variables). -* An optional hash of session variables to pass along with the request. -* An optional hash of flash values. +* The action of the controller you are requesting. + This can be in the form of a string or a symbol. + +* `params`: option with a hash of request parameters to pass into the action + (e.g. query string parameters or article variables). + +* `session`: option with a hash of session variables to pass along with the request. + +* `flash`: option with a hash of flash values. + +All the keyword arguments are optional. Example: Calling the `:show` action, passing an `id` of 12 as the `params` and setting a `user_id` of 5 in the session: ```ruby -get(:show, {'id' => "12"}, {'user_id' => 5}) +get(:show, params: { 'id' => "12" }, session: { 'user_id' => 5 }) ``` Another example: Calling the `:view` action, passing an `id` of 12 as the `params`, this time with no session, but with a flash message. ```ruby -get(:view, {'id' => '12'}, nil, {'message' => 'booya!'}) +get(:view, params: { 'id' => '12' }, flash: { 'message' => 'booya!' }) ``` NOTE: If you try running `test_should_create_article` test from `articles_controller_test.rb` it will fail on account of the newly added model level validation and rightly so. @@ -504,7 +519,7 @@ Let us modify `test_should_create_article` test in `articles_controller_test.rb` ```ruby test "should create article" do assert_difference('Article.count') do - post :create, article: {title: 'Some title'} + post :create, params: { article: { title: 'Some title' } } end assert_redirected_to article_path(assigns(:article)) @@ -530,11 +545,12 @@ NOTE: Functional tests do not verify whether the specified request type is accep ### Testing XHR (AJAX) requests -`xhr` accepts method (listed in the section above), action name and parameters: +To test AJAX requests, you can specify the `xhr: true` option to `get`, `post`, +`patch`, `put`, and `delete` methods: ```ruby test "ajax request responds with no layout" do - xhr :get, :show, id: articles(:first).id + get :show, params: { id: articles(:first).id }, xhr: true assert_template :index assert_template layout: nil @@ -638,7 +654,7 @@ Let's start by adding this assertion to our `test_should_create_article` test: ```ruby test "should create article" do assert_difference('Article.count') do - post :create, article: {title: 'Some title'} + post :create, params: { article: { title: 'Some title' } } end assert_redirected_to article_path(assigns(:article)) @@ -708,7 +724,7 @@ Let's write a test for the `:show` action: ```ruby test "should show article" do article = articles(:one) - get :show, id: article.id + get :show, params: { id: article.id } assert_response :success end ``` @@ -721,7 +737,7 @@ How about deleting an existing Article? test "should destroy article" do article = articles(:one) assert_difference('Article.count', -1) do - delete :destroy, id: article.id + delete :destroy, params: { id: article.id } end assert_redirected_to articles_path @@ -733,7 +749,7 @@ We can also add a test for updating an existing Article. ```ruby test "should update article" do article = articles(:one) - patch :update, id: article.id, article: {title: "updated"} + patch :update, params: { id: article.id, article: { title: "updated" } } assert_redirected_to article_path(assigns(:article)) end ``` @@ -759,20 +775,20 @@ class ArticlesControllerTest < ActionController::TestCase test "should show article" do # Reuse the @article instance variable from setup - get :show, id: @article.id + get :show, params: { id: @article.id } assert_response :success end test "should destroy article" do assert_difference('Article.count', -1) do - delete :destroy, id: @article.id + delete :destroy, params: { id: @article.id } end assert_redirected_to articles_path end test "should update article" do - patch :update, id: @article.id, article: {title: "updated"} + patch :update, params: { id: @article.id, article: { title: "updated" } } assert_redirected_to article_path(assigns(:article)) end end @@ -1026,7 +1042,8 @@ test "can create an article" do assert_response :success assert_template "articles/new", partial: "articles/_form" - post "/articles", article: {title: "can create", body: "article successfully."} + post "/articles", + params: { article: { title: "can create", body: "article successfully." } } assert_response :redirect follow_redirect! assert_response :success @@ -1042,7 +1059,8 @@ We start by calling the `:new` action on our Articles controller. This response After this we make a post request to the `:create` action of our Articles controller: ```ruby -post "/articles", article: {title: "can create", body: "article successfully."} +post "/articles", + params: { article: { title: "can create", body: "article successfully." } } assert_response :redirect follow_redirect! ``` @@ -1147,7 +1165,7 @@ require 'test_helper' class UserControllerTest < ActionController::TestCase test "invite friend" do assert_difference 'ActionMailer::Base.deliveries.size', +1 do - post :invite_friend, email: 'friend@example.com' + post :invite_friend, params: { email: 'friend@example.com' } end invite_email = ActionMailer::Base.deliveries.last @@ -1201,7 +1219,7 @@ within a model: ```ruby require 'test_helper' -class ProductTest < ActiveSupport::TestCase +class ProductTest < ActiveJob::TestCase test 'billing job scheduling' do assert_enqueued_with(job: BillingJob) do product.charge(account) diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md index d7fbe575c2..20b90bdba0 100644 --- a/guides/source/upgrading_ruby_on_rails.md +++ b/guides/source/upgrading_ruby_on_rails.md @@ -276,6 +276,22 @@ class Notifier < ActionMailer::Base end ``` +### Foreign Key Support + +The migration DSL has been expanded to support foreign key definitions. If +you've been using the Foreigner gem, you might want to consider removing it. +Note that the foreign key support of Rails is a subset of Foreigner. This means +that not every Foreigner definition can be fully replaced by it's Rails +migration DSL counterpart. + +The migration procedure is as follows: + +1. remove `gem "foreigner"` from the Gemfile. +2. run `bundle install`. +3. run `bin/rake db:schema:dump`. +4. make sure that `db/schema.rb` contains every foreign key definition with +the necessary options. + Upgrading from Rails 4.0 to Rails 4.1 ------------------------------------- @@ -534,7 +550,7 @@ module FixtureFileHelpers Digest::SHA2.hexdigest(File.read(Rails.root.join('test/fixtures', path))) end end -ActiveRecord::FixtureSet.context_class.send :include, FixtureFileHelpers +ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers ``` ### I18n enforcing available locales diff --git a/guides/source/working_with_javascript_in_rails.md b/guides/source/working_with_javascript_in_rails.md index 367abddcfa..e3856a285a 100644 --- a/guides/source/working_with_javascript_in_rails.md +++ b/guides/source/working_with_javascript_in_rails.md @@ -191,6 +191,34 @@ $(document).ready -> Obviously, you'll want to be a bit more sophisticated than that, but it's a start. You can see more about the events [in the jquery-ujs wiki](https://github.com/rails/jquery-ujs/wiki/ajax). +Another possibility is returning javascript directly from the server side on +remote calls: + +```ruby +# articles_controller +def create + respond_to do |format| + if @article.save + format.html { ... } + format.js do + render js: <<-endjs + alert('Article saved successfully!'); + window.location = '#{article_path(@article)}'; + endjs + end + else + format.html { ... } + format.js do + render js: "alert('There are empty fields in the form!');" + end + end + end +end +``` + +NOTE: If javascript is disabled in the user browser, `format.html { ... }` +block should be executed as fallback. + ### form_tag [`form_tag`](http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-form_tag) @@ -357,7 +385,7 @@ This gem uses Ajax to speed up page rendering in most applications. Turbolinks attaches a click handler to all `<a>` on the page. If your browser supports -[PushState](https://developer.mozilla.org/en-US/docs/DOM/Manipulating_the_browser_history#The_pushState(\).C2.A0method), +[PushState](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history#The_pushState()_method), Turbolinks will make an Ajax request for the page, parse the response, and replace the entire `<body>` of the page with the `<body>` of the response. It will then use PushState to change the URL to the correct one, preserving |