mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Convert all the links into Markdown format
This commit is contained in:
parent
31ef4cf656
commit
9873dd800b
31 changed files with 319 additions and 319 deletions
|
@ -18,11 +18,11 @@ What Does a Controller Do?
|
|||
|
||||
Action Controller is the C in MVC. After routing has determined which controller to use for a request, your controller is responsible for making sense of the request and producing the appropriate output. Luckily, Action Controller does most of the groundwork for you and uses smart conventions to make this as straightforward as possible.
|
||||
|
||||
For most conventional "RESTful":http://en.wikipedia.org/wiki/Representational_state_transfer applications, the controller will receive the request (this is invisible to you as the developer), fetch or save data from a model and use a view to create HTML output. If your controller needs to do things a little differently, that's not a problem, this is just the most common way for a controller to work.
|
||||
For most conventional [RESTful](http://en.wikipedia.org/wiki/Representational_state_transfer) applications, the controller will receive the request (this is invisible to you as the developer), fetch or save data from a model and use a view to create HTML output. If your controller needs to do things a little differently, that's not a problem, this is just the most common way for a controller to work.
|
||||
|
||||
A controller can thus be thought of as a middle man between models and views. It makes the model data available to the view so it can display that data to the user, and it saves or updates data from the user to the model.
|
||||
|
||||
NOTE: For more details on the routing process, see "Rails Routing from the Outside In":routing.html.
|
||||
NOTE: For more details on the routing process, see [Rails Routing from the Outside In](routing.html).
|
||||
|
||||
Methods and Actions
|
||||
-------------------
|
||||
|
@ -44,7 +44,7 @@ def new
|
|||
end
|
||||
```
|
||||
|
||||
The "Layouts & Rendering Guide":layouts_and_rendering.html explains this in more detail.
|
||||
The [Layouts & Rendering Guide](layouts_and_rendering.html) explains this in more detail.
|
||||
|
||||
`ApplicationController` inherits from `ActionController::Base`, which defines a number of helpful methods. This guide will cover some of these, but if you're curious to see what's in there, you can see all of them in the API documentation or in the source itself.
|
||||
|
||||
|
@ -138,7 +138,7 @@ And assume that you're sending the data to `CompaniesController`, it would then
|
|||
{ :name => "acme", :address => "123 Carrot Street", :company => { :name => "acme", :address => "123 Carrot Street" }}
|
||||
```
|
||||
|
||||
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
|
||||
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)
|
||||
|
||||
### Routing Parameters
|
||||
|
||||
|
@ -185,7 +185,7 @@ The CookieStore can store around 4kB of data -- much less than the others -- but
|
|||
|
||||
If your user sessions don't store critical data or don't need to be around for long periods (for instance if you just use the flash for messaging), you can consider using ActionDispatch::Session::CacheStore. This will store sessions using the cache implementation you have configured for your application. The advantage of this is that you can use your existing cache infrastructure for storing sessions without requiring any additional setup or administration. The downside, of course, is that the sessions will be ephemeral and could disappear at any time.
|
||||
|
||||
Read more about session storage in the "Security Guide":security.html.
|
||||
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:
|
||||
|
||||
|
@ -285,7 +285,7 @@ To reset the entire session, use `reset_session`.
|
|||
|
||||
The flash is a special part of the session which is cleared with each request. This means that values stored there will only be available in the next request, which is useful for passing error messages etc.
|
||||
|
||||
It is accessed in much the same way as the session, as a hash (it's a "FlashHash":http://api.rubyonrails.org/classes/ActionDispatch/Flash/FlashHash.html instance).
|
||||
It is accessed in much the same way as the session, as a hash (it's a [FlashHash](http://api.rubyonrails.org/classes/ActionDispatch/Flash/FlashHash.html) instance).
|
||||
|
||||
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:
|
||||
|
||||
|
@ -567,11 +567,11 @@ You will see how the token gets added as a hidden field:
|
|||
</form>
|
||||
```
|
||||
|
||||
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`:
|
||||
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`:
|
||||
|
||||
The `form_authenticity_token` generates a valid authentication token. That's useful in places where Rails does not add it automatically, like in custom Ajax calls.
|
||||
|
||||
The "Security Guide":security.html has more about this and a lot of other security-related issues that you should be aware of when developing a web application.
|
||||
The [Security Guide](security.html) has more about this and a lot of other security-related issues that you should be aware of when developing a web application.
|
||||
|
||||
The Request and Response Objects
|
||||
--------------------------------
|
||||
|
@ -580,7 +580,7 @@ In every controller there are two accessor methods pointing to the request and t
|
|||
|
||||
### The `request` Object
|
||||
|
||||
The request object contains a lot of useful information about the request coming in from the client. To get a full list of the available methods, refer to the "API documentation":http://api.rubyonrails.org/classes/ActionDispatch/Request.html. Among the properties that you can access on this object are:
|
||||
The request object contains a lot of useful information about the request coming in from the client. To get a full list of the available methods, refer to the [API documentation](http://api.rubyonrails.org/classes/ActionDispatch/Request.html). Among the properties that you can access on this object are:
|
||||
|
||||
|_.Property of `request`|_.Purpose|
|
||||
|host|The hostname used for this request.|
|
||||
|
@ -822,7 +822,7 @@ class ClientsController < ApplicationController
|
|||
end
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
Force HTTPS protocol
|
||||
--------------------
|
||||
|
|
|
@ -49,7 +49,7 @@ The complete HTML returned to the client is composed of a combination of this ER
|
|||
Using Action View outside of Rails
|
||||
----------------------------------
|
||||
|
||||
Action View works well with Action Record, but it can also be used with other Ruby tools. We can demonstrate this by creating a small "Rack":http://rack.rubyforge.org/ application that includes Action View functionality. This may be useful, for example, if you'd like access to Action View's helpers in a Rack application.
|
||||
Action View works well with Action Record, but it can also be used with other Ruby tools. We can demonstrate this by creating a small [Rack](http://rack.rubyforge.org/) application that includes Action View functionality. This may be useful, for example, if you'd like access to Action View's helpers in a Rack application.
|
||||
|
||||
Let's start by ensuring that you have the Action Pack and Rack gems installed:
|
||||
|
||||
|
@ -83,7 +83,7 @@ TODO needs a screenshot? I have one - not sure where to put it.
|
|||
|
||||
Notice how 'hello world' has been converted into 'Hello World' by the `titleize` helper method.
|
||||
|
||||
Action View can also be used with "Sinatra":http://www.sinatrarb.com/ in the same way.
|
||||
Action View can also be used with [Sinatra](http://www.sinatrarb.com/) in the same way.
|
||||
|
||||
Let's start by ensuring that you have the Action Pack and Sinatra gems installed:
|
||||
|
||||
|
@ -408,7 +408,7 @@ The following is only a brief overview summary of the helpers available in Actio
|
|||
|
||||
### ActiveRecordHelper
|
||||
|
||||
The Active Record Helper makes it easier to create forms for records kept in instance variables. You may also want to review the "Rails Form helpers guide":form_helpers.html.
|
||||
The Active Record Helper makes it easier to create forms for records kept in instance variables. You may also want to review the [Rails Form helpers guide](form_helpers.html).
|
||||
|
||||
#### error_message_on
|
||||
|
||||
|
@ -1603,4 +1603,4 @@ end
|
|||
|
||||
Then you could create special views like `app/views/posts/show.expert.html.erb` that would only be displayed to expert users.
|
||||
|
||||
You can read more about the Rails Internationalization (I18n) API "here":i18n.html.
|
||||
You can read more about the Rails Internationalization (I18n) API [here](i18n.html).
|
||||
|
|
|
@ -14,7 +14,7 @@ This guide is an introduction to Active Record. After reading this guide we hope
|
|||
What is Active Record?
|
||||
----------------------
|
||||
|
||||
Active Record is the M in "MVC":getting_started.html#the-mvc-architecture - the model - which is the layer of the system responsible for representing business data and logic. Active Record facilitates the creation and use of business objects whose data requires persistent storage to a database. It is an implementation of the Active Record pattern which itself is a description of an Object Relational Mapping system.
|
||||
Active Record is the M in [MVC](getting_started.html#the-mvc-architecture) - the model - which is the layer of the system responsible for representing business data and logic. Active Record facilitates the creation and use of business objects whose data requires persistent storage to a database. It is an implementation of the Active Record pattern which itself is a description of an Object Relational Mapping system.
|
||||
|
||||
### The Active Record Pattern
|
||||
|
||||
|
@ -59,7 +59,7 @@ By default, Active Record uses some naming conventions to find out how the mappi
|
|||
Active Record uses naming conventions for the columns in database tables, depending on the purpose of these columns.
|
||||
|
||||
* *Foreign keys* - These fields should be named following the pattern `singularized_table_name_id` (e.g., `item_id`, `order_id`). These are the fields that Active Record will look for when you create associations between your models.
|
||||
* *Primary keys* - By default, Active Record will use an integer column named `id` as the table's primary key. When using "Rails Migrations":migrations.html to create your tables, this column will be automatically created.
|
||||
* *Primary keys* - By default, Active Record will use an integer column named `id` as the table's primary key. When using [Rails Migrations](migrations.html) to create your tables, this column will be automatically created.
|
||||
|
||||
There are also some optional column names that will create additional features to Active Record instances:
|
||||
|
||||
|
@ -67,8 +67,8 @@ There are also some optional column names that will create additional features t
|
|||
* `created_on` - Automatically gets set to the current date when the record is first created.
|
||||
* `updated_at` - Automatically gets set to the current date and time whenever the record is updated.
|
||||
* `updated_on` - Automatically gets set to the current date whenever the record is updated.
|
||||
* `lock_version` - Adds "optimistic locking":http://api.rubyonrails.org/classes/ActiveRecord/Locking.html to a model.
|
||||
* `type` - Specifies that the model uses "Single Table Inheritance":http://api.rubyonrails.org/classes/ActiveRecord/Base.html
|
||||
* `lock_version` - Adds [optimistic locking](http://api.rubyonrails.org/classes/ActiveRecord/Locking.html) to a model.
|
||||
* `type` - Specifies that the model uses [Single Table Inheritance](http://api.rubyonrails.org/classes/ActiveRecord/Base.html)
|
||||
* `(table_name)_count` - Used to cache the number of belonging objects on associations. For example, a `comments_count` column in a `Post` class that has many instances of `Comment` will cache the number of existent comments for each post.
|
||||
|
||||
NOTE: While these column names are optional, they are in fact reserved by Active Record. Steer clear of reserved keywords unless you want the extra functionality. For example, `type` is a reserved keyword used to designate a table using Single Table Inheritance (STI). If you are not using STI, try an analogous keyword like "context", that may still accurately describe the data you are modeling.
|
||||
|
@ -190,7 +190,7 @@ Active Record provides a rich API for accessing data within a database. Below ar
|
|||
users = User.where(:name => 'David', :occupation => 'Code Artist').order('created_at DESC')
|
||||
```
|
||||
|
||||
You can learn more about querying an Active Record model in the "Active Record Query Interface":"active_record_querying.html" guide.
|
||||
You can learn more about querying an Active Record model in the [Active Record Query Interface](active_record_querying.html) guide.
|
||||
|
||||
### Update
|
||||
|
||||
|
@ -214,14 +214,14 @@ Likewise, once retrieved an Active Record object can be destroyed which removes
|
|||
Validations
|
||||
-----------
|
||||
|
||||
Active Record allows you to validate the state of a model before it gets written into the database. There are several methods that you can use to check your models and validate that an attribute value is not empty, is unique and not already in the database, follows a specific format and many more. You can learn more about validations in the "Active Record Validations and Callbacks guide":active_record_validations_callbacks.html#validations-overview.
|
||||
Active Record allows you to validate the state of a model before it gets written into the database. There are several methods that you can use to check your models and validate that an attribute value is not empty, is unique and not already in the database, follows a specific format and many more. You can learn more about validations in the [Active Record Validations and Callbacks guide](active_record_validations_callbacks.html#validations-overview).
|
||||
|
||||
Callbacks
|
||||
---------
|
||||
|
||||
Active Record callbacks allow you to attach code to certain events in the life-cycle of your models. This enables you to add behavior to your models by transparently executing code when those events occur, like when you create a new record, update it, destroy it and so on. You can learn more about callbacks in the "Active Record Validations and Callbacks guide":active_record_validations_callbacks.html#callbacks-overview.
|
||||
Active Record callbacks allow you to attach code to certain events in the life-cycle of your models. This enables you to add behavior to your models by transparently executing code when those events occur, like when you create a new record, update it, destroy it and so on. You can learn more about callbacks in the [Active Record Validations and Callbacks guide](active_record_validations_callbacks.html#callbacks-overview).
|
||||
|
||||
Migrations
|
||||
----------
|
||||
|
||||
Rails provides a domain-specific language for managing a database schema called migrations. Migrations are stored in files which are executed against any database that Active Record support using rake. Rails keeps track of which files have been committed to the database and provides rollback features. You can learn more about migrations in the "Active Record Migrations guide":migrations.html
|
||||
Rails provides a domain-specific language for managing a database schema called migrations. Migrations are stored in files which are executed against any database that Active Record support using rake. Rails keeps track of which files have been committed to the database and provides rollback features. You can learn more about migrations in the [Active Record Migrations guide](migrations.html)
|
||||
|
|
|
@ -437,7 +437,7 @@ Client.where("orders_count = #{params[:orders]}")
|
|||
|
||||
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.
|
||||
|
||||
TIP: For more information on the dangers of SQL injection, see the "Ruby on Rails Security Guide":security.html#sql-injection.
|
||||
TIP: For more information on the dangers of SQL injection, see the [Ruby on Rails Security Guide](security.html#sql-injection).
|
||||
|
||||
#### Placeholder Conditions
|
||||
|
||||
|
@ -489,7 +489,7 @@ This will find all clients created yesterday by using a `BETWEEN` SQL statement:
|
|||
SELECT * FROM clients WHERE (clients.created_at BETWEEN '2008-12-21 00:00:00' AND '2008-12-22 00:00:00')
|
||||
```
|
||||
|
||||
This demonstrates a shorter syntax for the examples in "Array Conditions":#array-conditions
|
||||
This demonstrates a shorter syntax for the examples in [Array Conditions](#array-conditions)
|
||||
|
||||
#### Subset Conditions
|
||||
|
||||
|
@ -546,7 +546,7 @@ By default, `Model.find` selects all the fields from the result set using `selec
|
|||
|
||||
To select only a subset of fields from the result set, you can specify the subset via the `select` method.
|
||||
|
||||
NOTE: If the `select` method is used, all the returning objects will be "read only":#readonly-objects.
|
||||
NOTE: If the `select` method is used, all the returning objects will be [read only](#readonly-objects).
|
||||
|
||||
<br />
|
||||
|
||||
|
@ -894,7 +894,7 @@ SELECT clients.* FROM clients LEFT OUTER JOIN addresses ON addresses.client_id =
|
|||
|
||||
WARNING: This method only works with `INNER JOIN`.
|
||||
|
||||
Active Record lets you use the names of the "associations":association_basics.html defined on the model as a shortcut for specifying `JOIN` clause for those associations when using the `joins` method.
|
||||
Active Record lets you use the names of the [associations](association_basics.html) defined on the model as a shortcut for specifying `JOIN` clause for those associations when using the `joins` method.
|
||||
|
||||
For example, consider the following `Category`, `Post`, `Comments` and `Guest` models:
|
||||
|
||||
|
@ -990,7 +990,7 @@ SELECT categories.* FROM categories
|
|||
|
||||
### 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:
|
||||
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
|
||||
time_range = (Time.now.midnight - 1.day)..Time.now.midnight
|
||||
|
@ -1069,7 +1069,7 @@ This will find the category with id 1 and eager load all of the associated posts
|
|||
|
||||
### Specifying Conditions on Eager Loaded Associations
|
||||
|
||||
Even though Active Record lets you specify conditions on the eager loaded associations just like `joins`, the recommended way is to use "joins":#joining-tables instead.
|
||||
Even though Active Record lets you specify conditions on the eager loaded associations just like `joins`, the recommended way is to use [joins](#joining-tables) instead.
|
||||
|
||||
However if you must do this, you may use `where` as you would normally.
|
||||
|
||||
|
@ -1475,7 +1475,7 @@ SELECT count(DISTINCT clients.id) AS count_all FROM clients
|
|||
|
||||
If you want to see how many records are in your model's table you could call `Client.count` and that will return the number. If you want to be more specific and find all the clients with their age present in the database you can use `Client.count(:age)`.
|
||||
|
||||
For options, please see the parent section, "Calculations":#calculations.
|
||||
For options, please see the parent section, [Calculations](#calculations).
|
||||
|
||||
### Average
|
||||
|
||||
|
@ -1487,7 +1487,7 @@ Client.average("orders_count")
|
|||
|
||||
This will return a number (possibly a floating point number such as 3.14159265) representing the average value in the field.
|
||||
|
||||
For options, please see the parent section, "Calculations":#calculations.
|
||||
For options, please see the parent section, [Calculations](#calculations).
|
||||
|
||||
### Minimum
|
||||
|
||||
|
@ -1497,7 +1497,7 @@ If you want to find the minimum value of a field in your table you can call the
|
|||
Client.minimum("age")
|
||||
```
|
||||
|
||||
For options, please see the parent section, "Calculations":#calculations.
|
||||
For options, please see the parent section, [Calculations](#calculations).
|
||||
|
||||
### Maximum
|
||||
|
||||
|
@ -1507,7 +1507,7 @@ If you want to find the maximum value of a field in your table you can call the
|
|||
Client.maximum("age")
|
||||
```
|
||||
|
||||
For options, please see the parent section, "Calculations":#calculations.
|
||||
For options, please see the parent section, [Calculations](#calculations).
|
||||
|
||||
### Sum
|
||||
|
||||
|
@ -1517,7 +1517,7 @@ If you want to find the sum of a field for all records in your table you can cal
|
|||
Client.sum("orders_count")
|
||||
```
|
||||
|
||||
For options, please see the parent section, "Calculations":#calculations.
|
||||
For options, please see the parent section, [Calculations](#calculations).
|
||||
|
||||
Running EXPLAIN
|
||||
---------------
|
||||
|
@ -1633,8 +1633,8 @@ Explicit calls to `ActiveRecord::Relation#explain` run.
|
|||
Interpretation of the output of EXPLAIN is beyond the scope of this guide. The
|
||||
following pointers may be helpful:
|
||||
|
||||
* SQLite3: "EXPLAIN QUERY PLAN":http://www.sqlite.org/eqp.html
|
||||
* SQLite3: [EXPLAIN QUERY PLAN](http://www.sqlite.org/eqp.html)
|
||||
|
||||
* MySQL: "EXPLAIN Output Format":http://dev.mysql.com/doc/refman/5.6/en/explain-output.html
|
||||
* MySQL: [EXPLAIN Output Format](http://dev.mysql.com/doc/refman/5.6/en/explain-output.html)
|
||||
|
||||
* PostgreSQL: "Using EXPLAIN":http://www.postgresql.org/docs/current/static/using-explain.html
|
||||
* PostgreSQL: [Using EXPLAIN](http://www.postgresql.org/docs/current/static/using-explain.html)
|
||||
|
|
|
@ -35,7 +35,7 @@ There are several ways to validate data before it is saved into your database, i
|
|||
|
||||
* Database constraints and/or stored procedures make the validation mechanisms database-dependent and can make testing and maintenance more difficult. However, if your database is used by other applications, it may be a good idea to use some constraints at the database level. Additionally, database-level validations can safely handle some things (such as uniqueness in heavily-used tables) that can be difficult to implement otherwise.
|
||||
* Client-side validations can be useful, but are generally unreliable if used alone. If they are implemented using JavaScript, they may be bypassed if JavaScript is turned off in the user's browser. However, if combined with other techniques, client-side validation can be a convenient way to provide users with immediate feedback as they use your site.
|
||||
* Controller-level validations can be tempting to use, but often become unwieldy and difficult to test and maintain. Whenever possible, it's a good idea to "keep your controllers skinny":http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model, as it will make your application a pleasure to work with in the long run.
|
||||
* Controller-level validations can be tempting to use, but often become unwieldy and difficult to test and maintain. Whenever possible, it's a good idea to [keep your controllers skinny](http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model), as it will make your application a pleasure to work with in the long run.
|
||||
* Model-level validations are the best way to ensure that only valid data is saved into your database. They are database agnostic, cannot be bypassed by end users, and are convenient to test and maintain. Rails makes them easy to use, provides built-in helpers for common needs, and allows you to create your own validation methods as well.
|
||||
|
||||
### When Does Validation Happen?
|
||||
|
@ -160,7 +160,7 @@ end
|
|||
>> Person.create.errors[:name].any? # => true
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
Validation Helpers
|
||||
------------------
|
||||
|
@ -857,7 +857,7 @@ person.errors.size # => 0
|
|||
Displaying Validation Errors in the View
|
||||
----------------------------------------
|
||||
|
||||
"DynamicForm":https://github.com/joelmoss/dynamic_form provides helpers to display the error messages of your models in your view templates.
|
||||
[DynamicForm](https://github.com/joelmoss/dynamic_form) provides helpers to display the error messages of your models in your view templates.
|
||||
|
||||
You can install it as a gem by adding this line to your Gemfile:
|
||||
|
||||
|
@ -899,7 +899,7 @@ If you submit the form with empty fields, the result will be similar to the one
|
|||
|
||||
!images/error_messages.png(Error messages)!
|
||||
|
||||
NOTE: The appearance of the generated HTML will be different from the one shown, unless you have used scaffolding. See "Customizing the Error Messages CSS":#customizing-error-messages-css.
|
||||
NOTE: The appearance of the generated HTML will be different from the one shown, unless you have used scaffolding. See [Customizing the Error Messages CSS](#customizing-error-messages-css).
|
||||
|
||||
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.
|
||||
|
||||
|
|
|
@ -610,7 +610,7 @@ NOTE: Defined in `active_support/core_ext/module/attr_internal.rb`.
|
|||
|
||||
#### Module Attributes
|
||||
|
||||
The macros `mattr_reader`, `mattr_writer`, and `mattr_accessor` are analogous to the `cattr_*` macros defined for class. Check "Class Attributes":#class-attributes.
|
||||
The macros `mattr_reader`, `mattr_writer`, and `mattr_accessor` are analogous to the `cattr_*` macros defined for class. Check [Class Attributes](#class-attributes).
|
||||
|
||||
For example, the dependencies mechanism uses them:
|
||||
|
||||
|
@ -1151,7 +1151,7 @@ Extensions to `String`
|
|||
|
||||
#### Motivation
|
||||
|
||||
Inserting data into HTML templates needs extra care. For example, you can't just interpolate `@review.title` verbatim into an HTML page. For one thing, if the review title is "Flanagan & Matz rules!" the output won't be well-formed because an ampersand has to be escaped as "&amp;". What's more, depending on the application, that may be a big security hole because users can inject malicious HTML setting a hand-crafted review title. Check out the "section about cross-site scripting in the Security guide":security.html#cross-site-scripting-xss for further information about the risks.
|
||||
Inserting data into HTML templates needs extra care. For example, you can't just interpolate `@review.title` verbatim into an HTML page. For one thing, if the review title is "Flanagan & Matz rules!" the output won't be well-formed because an ampersand has to be escaped as "&amp;". What's more, depending on the application, that may be a big security hole because users can inject malicious HTML setting a hand-crafted review title. Check out the "section about cross-site scripting in the [Security guide](security.html#cross-site-scripting-xss) for further information about the risks.
|
||||
|
||||
#### Safe Strings
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ that gets returned, and the page is not reloaded.
|
|||
Built-in Rails Helpers
|
||||
----------------------
|
||||
|
||||
Rails 4.0 ships with "jQuery":http://jquery.com as the default JavaScript library.
|
||||
Rails 4.0 ships with [jQuery](http://jquery.com) as the default JavaScript library.
|
||||
The Gemfile contains `gem 'jquery-rails'` which provides the `jquery.js` and
|
||||
`jquery_ujs.js` files via the asset pipeline.
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ This guide documents the Ruby on Rails API documentation guidelines.
|
|||
RDoc
|
||||
----
|
||||
|
||||
The Rails API documentation is generated with RDoc. Please consult the documentation for help with the "markup":http://rdoc.rubyforge.org/RDoc/Markup.html, and also take into account these "additional directives":http://rdoc.rubyforge.org/RDoc/Parser/Ruby.html.
|
||||
The Rails API documentation is generated with RDoc. Please consult the documentation for help with the [markup](http://rdoc.rubyforge.org/RDoc/Markup.html), and also take into account these [additional directives](http://rdoc.rubyforge.org/RDoc/Parser/Ruby.html).
|
||||
|
||||
Wording
|
||||
-------
|
||||
|
@ -39,14 +39,14 @@ Use the article "an" for "SQL", as in "an SQL statement". Also "an SQLite databa
|
|||
English
|
||||
-------
|
||||
|
||||
Please use American English (<em>color</em>, <em>center</em>, <em>modularize</em>, etc.). See "a list of American and British English spelling differences here":http://en.wikipedia.org/wiki/American_and_British_English_spelling_differences.
|
||||
Please use American English (<em>color</em>, <em>center</em>, <em>modularize</em>, etc).. See [a list of American and British English spelling differences here](http://en.wikipedia.org/wiki/American_and_British_English_spelling_differences).
|
||||
|
||||
Example Code
|
||||
------------
|
||||
|
||||
Choose meaningful examples that depict and cover the basics as well as interesting points or gotchas.
|
||||
|
||||
Use two spaces to indent chunks of code--that is, for markup purposes, two spaces with respect to the left margin. The examples themselves should use "Rails coding conventions":contributing_to_ruby_on_rails.html#follow-the-coding-conventions.
|
||||
Use two spaces to indent chunks of code--that is, for markup purposes, two spaces with respect to the left margin. The examples themselves should use [Rails coding conventions](contributing_to_ruby_on_rails.html#follow-the-coding-conventions).
|
||||
|
||||
Short docs do not need an explicit "Examples" label to introduce snippets; they just follow paragraphs:
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ The query string strategy has several disadvantages:
|
|||
<ol>
|
||||
<li>
|
||||
<strong>Not all caches will reliably cache content where the filename only differs by query parameters</strong>.<br />
|
||||
"Steve Souders recommends":http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/, "...avoiding a querystring for cacheable resources". He found that in this case 5-20% of requests will not be cached. Query strings in particular do not work at all with some CDNs for cache invalidation.
|
||||
[Steve Souders recommends](http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/), "...avoiding a querystring for cacheable resources". He found that in this case 5-20% of requests will not be cached. Query strings in particular do not work at all with some CDNs for cache invalidation.
|
||||
</li>
|
||||
<li>
|
||||
<strong>The file name can change between nodes in multi-server environments.</strong><br />
|
||||
|
@ -91,8 +91,8 @@ Fingerprinting is enabled by default for production and disabled for all other e
|
|||
|
||||
More reading:
|
||||
|
||||
* "Optimize caching":http://code.google.com/speed/page-speed/docs/caching.html
|
||||
* "Revving Filenames: don’t use querystring":http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/
|
||||
* [Optimize caching](http://code.google.com/speed/page-speed/docs/caching.html)
|
||||
* [Revving Filenames: don’t use querystring](http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/)
|
||||
|
||||
|
||||
How to Use the Asset Pipeline
|
||||
|
@ -108,7 +108,7 @@ When you generate a scaffold or a controller, Rails also generates a JavaScript
|
|||
|
||||
For example, if you generate a `ProjectsController`, Rails will also add a new file at `app/assets/javascripts/projects.js.coffee` and another at `app/assets/stylesheets/projects.css.scss`. You should put any JavaScript or CSS unique to a controller inside their respective asset files, as these files can then be loaded just for these controllers with lines such as `<%= javascript_include_tag params[:controller] %>` or `<%= stylesheet_link_tag params[:controller] %>`.
|
||||
|
||||
NOTE: You must have an "ExecJS":https://github.com/sstephenson/execjs#readme supported runtime in order to use CoffeeScript. If you are using Mac OS X or Windows you have a JavaScript runtime installed in your operating system. Check "ExecJS":https://github.com/sstephenson/execjs#readme documentation to know all supported JavaScript runtimes.
|
||||
NOTE: You must have an [ExecJS](https://github.com/sstephenson/execjs#readme) supported runtime in order to use CoffeeScript. If you are using Mac OS X or Windows you have a JavaScript runtime installed in your operating system. Check [ExecJS](https://github.com/sstephenson/execjs#readme) documentation to know all supported JavaScript runtimes.
|
||||
|
||||
### Asset Organization
|
||||
|
||||
|
@ -199,7 +199,7 @@ In regular views you can access images in the `assets/images` directory like thi
|
|||
|
||||
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.
|
||||
|
||||
Alternatively, a request for a file with an MD5 hash such as `public/assets/rails-af27b6a414e6da00003503148be9b409.png` is treated the same way. How these hashes are generated is covered in the "In Production":#in-production section later on in this guide.
|
||||
Alternatively, a request for a file with an MD5 hash such as `public/assets/rails-af27b6a414e6da00003503148be9b409.png` is treated the same way. How these hashes are generated is covered in the [In Production](#in-production) section later on in this guide.
|
||||
|
||||
Sprockets will also look through the paths specified in `config.assets.paths` which includes the standard application paths and any path added by Rails engines.
|
||||
|
||||
|
@ -209,7 +209,7 @@ Images can also be organized into subdirectories if required, and they can be ac
|
|||
<%= image_tag "icons/rails.png" %>
|
||||
```
|
||||
|
||||
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 `image_tag` and the other helpers with user-supplied data.
|
||||
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 `image_tag` and the other helpers with user-supplied data.
|
||||
|
||||
#### CSS and ERB
|
||||
|
||||
|
@ -221,7 +221,7 @@ The asset pipeline automatically evaluates ERB. This means that if you add an `e
|
|||
|
||||
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.
|
||||
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.
|
||||
|
||||
```
|
||||
#logo { background: url(<%= asset_data_uri 'logo.png' %>) }
|
||||
|
@ -295,7 +295,7 @@ The directives that work in the JavaScript files also work in stylesheets (thoug
|
|||
|
||||
In this example `require_self` is used. This puts the CSS contained within the file (if any) at the precise location of the `require_self` call. If `require_self` is called more than once, only the last call is respected.
|
||||
|
||||
NOTE. If you want to use multiple Sass files, you should generally use the "Sass `@import` rule":http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#import instead of these Sprockets directives. Using Sprockets directives all Sass files exist within their own scope, making variables or mixins only available within the document they were defined in.
|
||||
NOTE. If you want to use multiple Sass files, you should generally use the [Sass `@import` rule](http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#import) instead of these Sprockets directives. Using Sprockets directives all Sass files exist within their own scope, making variables or mixins only available within the document they were defined in.
|
||||
|
||||
You can have as many manifest files as you need. For example the `admin.css` and `admin.js` manifest could contain the JS and CSS files that are used for the admin section of an application.
|
||||
|
||||
|
@ -503,7 +503,7 @@ location ~ ^/assets/ {
|
|||
|
||||
#### GZip compression
|
||||
|
||||
When files are precompiled, Sprockets also creates a "gzipped":http://en.wikipedia.org/wiki/Gzip (.gz) version of your assets. Web servers are typically configured to use a moderate compression ratio as a compromise, but since precompilation happens once, Sprockets uses the maximum compression ratio, thus reducing the size of the data transfer to the minimum. On the other hand, web servers can be configured to serve compressed content directly from disk, rather than deflating non-compressed files themselves.
|
||||
When files are precompiled, Sprockets also creates a [gzipped](http://en.wikipedia.org/wiki/Gzip) (.gz) version of your assets. Web servers are typically configured to use a moderate compression ratio as a compromise, but since precompilation happens once, Sprockets uses the maximum compression ratio, thus reducing the size of the data transfer to the minimum. On the other hand, web servers can be configured to serve compressed content directly from disk, rather than deflating non-compressed files themselves.
|
||||
|
||||
Nginx is able to do this automatically enabling `gzip_static`:
|
||||
|
||||
|
@ -590,7 +590,7 @@ Customizing the Pipeline
|
|||
|
||||
### CSS Compression
|
||||
|
||||
There is currently one option for compressing CSS, YUI. The "YUI CSS compressor":http://developer.yahoo.com/yui/compressor/css.html provides minification.
|
||||
There is currently one option for compressing CSS, YUI. The [YUI CSS compressor](http://developer.yahoo.com/yui/compressor/css.html) provides minification.
|
||||
|
||||
The following line enables YUI compression, and requires the `yui-compressor` gem.
|
||||
|
||||
|
@ -604,7 +604,7 @@ The `config.assets.compress` must be set to `true` to enable CSS compression.
|
|||
|
||||
Possible options for JavaScript compression are `:closure`, `:uglifier` and `:yui`. These require the use of the `closure-compiler`, `uglifier` or `yui-compressor` gems, respectively.
|
||||
|
||||
The default Gemfile includes "uglifier":https://github.com/lautis/uglifier. This gem wraps "UglifierJS":https://github.com/mishoo/UglifyJS (written for NodeJS) in Ruby. It compresses your code by removing white space. It also includes other optimizations such as changing your `if` and `else` statements to ternary operators where possible.
|
||||
The default Gemfile includes [uglifier](https://github.com/lautis/uglifier). This gem wraps [UglifierJS](https://github.com/mishoo/UglifyJS) (written for NodeJS) in Ruby. It compresses your code by removing white space. It also includes other optimizations such as changing your `if` and `else` statements to ternary operators where possible.
|
||||
|
||||
The following line invokes `uglifier` for JavaScript compression.
|
||||
|
||||
|
@ -614,7 +614,7 @@ config.assets.js_compressor = :uglifier
|
|||
|
||||
Note that `config.assets.compress` must be set to `true` to enable JavaScript compression
|
||||
|
||||
NOTE: You will need an "ExecJS":https://github.com/sstephenson/execjs#readme supported runtime in order to use `uglifier`. If you are using Mac OS X or Windows you have a JavaScript runtime installed in your operating system. Check the "ExecJS":https://github.com/sstephenson/execjs#readme documentation for information on all of the supported JavaScript runtimes.
|
||||
NOTE: You will need an [ExecJS](https://github.com/sstephenson/execjs#readme) supported runtime in order to use `uglifier`. If you are using Mac OS X or Windows you have a JavaScript runtime installed in your operating system. Check the [ExecJS](https://github.com/sstephenson/execjs#readme) documentation for information on all of the supported JavaScript runtimes.
|
||||
|
||||
### Using Your Own Compressor
|
||||
|
||||
|
@ -685,12 +685,12 @@ A good example of this is the `jquery-rails` gem which comes with Rails as the s
|
|||
Making Your Library or Gem a Pre-Processor
|
||||
------------------------------------------
|
||||
|
||||
TODO: Registering gems on "Tilt":https://github.com/rtomayko/tilt enabling Sprockets to find them.
|
||||
TODO: Registering gems on [Tilt](https://github.com/rtomayko/tilt) enabling Sprockets to find them.
|
||||
|
||||
Upgrading from Old Versions of Rails
|
||||
------------------------------------
|
||||
|
||||
There are a few issues when upgrading. The first is moving the files from `public/` to the new locations. See "Asset Organization":#asset-organization above for guidance on the correct locations for different file types.
|
||||
There are a few issues when upgrading. The first is moving the files from `public/` to the new locations. See [Asset Organization](#asset-organization) above for guidance on the correct locations for different file types.
|
||||
|
||||
Next will be avoiding duplicate JavaScript files. Since jQuery is the default JavaScript library from Rails 3.1 onwards, you don't need to copy `jquery.js` into `app/assets` and it will be included automatically.
|
||||
|
||||
|
|
|
@ -785,7 +785,7 @@ class Order < ActiveRecord::Base
|
|||
end
|
||||
```
|
||||
|
||||
You can use any of the standard "querying methods":active_record_querying.html inside the scope block. The following ones are discussed below:
|
||||
You can use any of the standard [querying methods](active_record_querying.html) inside the scope block. The following ones are discussed below:
|
||||
|
||||
* `where`
|
||||
* `includes`
|
||||
|
@ -1038,7 +1038,7 @@ class Supplier < ActiveRecord::Base
|
|||
end
|
||||
```
|
||||
|
||||
You can use any of the standard "querying methods":active_record_querying.html inside the scope block. The following ones are discussed below:
|
||||
You can use any of the standard [querying methods](active_record_querying.html) inside the scope block. The following ones are discussed below:
|
||||
|
||||
* `where`
|
||||
* `includes`
|
||||
|
@ -1383,7 +1383,7 @@ class Customer < ActiveRecord::Base
|
|||
end
|
||||
```
|
||||
|
||||
You can use any of the standard "querying methods":active_record_querying.html inside the scope block. The following ones are discussed below:
|
||||
You can use any of the standard [querying methods](active_record_querying.html) inside the scope block. The following ones are discussed below:
|
||||
|
||||
* `where`
|
||||
* `extending`
|
||||
|
@ -1790,7 +1790,7 @@ class Parts < ActiveRecord::Base
|
|||
end
|
||||
```
|
||||
|
||||
You can use any of the standard "querying methods":active_record_querying.html inside the scope block. The following ones are discussed below:
|
||||
You can use any of the standard [querying methods](active_record_querying.html) inside the scope block. The following ones are discussed below:
|
||||
|
||||
* `where`
|
||||
* `extending`
|
||||
|
|
|
@ -378,7 +378,7 @@ config.cache_store = :ehcache_store
|
|||
|
||||
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).
|
||||
|
||||
In addition to the standard `:expires_in` option, the `write` method on this cache can also accept the additional `:unless_exist` option, which will cause the cache store to use Ehcache's `putIfAbsent` method instead of `put`, and therefore will not overwrite an existing entry. Additionally, the `write` method supports all of the properties exposed by the "Ehcache Element class":http://ehcache.org/apidocs/net/sf/ehcache/Element.html , including:
|
||||
In addition to the standard `:expires_in` option, the `write` method on this cache can also accept the additional `:unless_exist` option, which will cause the cache store to use Ehcache's `putIfAbsent` method instead of `put`, and therefore will not overwrite an existing entry. Additionally, the `write` method supports all of the properties exposed by the [Ehcache Element class](http://ehcache.org/apidocs/net/sf/ehcache/Element.html) , including:
|
||||
|
||||
|_. Property |_. Argument Type |_. Description |
|
||||
| elementEvictionData | ElementEvictionData | Sets this element's eviction data instance. |
|
||||
|
@ -394,8 +394,8 @@ Rails.cache.write('key', 'value', :time_to_idle => 60.seconds, :timeToLive => 60
|
|||
caches_action :index, :expires_in => 60.seconds, :unless_exist => true
|
||||
```
|
||||
|
||||
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
|
||||
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)
|
||||
|
||||
### ActiveSupport::Cache::NullStore
|
||||
|
||||
|
@ -488,4 +488,4 @@ end
|
|||
Further reading
|
||||
---------------
|
||||
|
||||
* "Scaling Rails Screencasts":http://railslab.newrelic.com/scaling-rails
|
||||
* [Scaling Rails Screencasts](http://railslab.newrelic.com/scaling-rails)
|
||||
|
|
|
@ -11,7 +11,7 @@ Rails comes with every command line tool you'll need to
|
|||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
NOTE: This tutorial assumes you have basic Rails knowledge from reading the "Getting Started with Rails Guide":getting_started.html.
|
||||
NOTE: This tutorial assumes you have basic Rails knowledge from reading the [Getting Started with Rails Guide](getting_started.html).
|
||||
|
||||
WARNING. This Guide is based on Rails 3.2. Some of the code shown here will not work in earlier versions of Rails.
|
||||
|
||||
|
@ -56,7 +56,7 @@ Rails will set you up with what seems like a huge amount of stuff for such a tin
|
|||
|
||||
The `rails server` command launches a small web server named WEBrick which comes bundled with Ruby. You'll use this any time you want to access your application through a web browser.
|
||||
|
||||
INFO: WEBrick isn't your only option for serving Rails. We'll get to that "later":#different-servers.
|
||||
INFO: WEBrick isn't your only option for serving Rails. We'll get to that [later](#different-servers).
|
||||
|
||||
With no further work, `rails server` will run our new shiny Rails app:
|
||||
|
||||
|
@ -72,7 +72,7 @@ $ rails server
|
|||
[2012-05-28 00:39:41] INFO WEBrick::HTTPServer#start: pid=69680 port=3000
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
INFO: You can also use the alias "s" to start the server: `rails s`.
|
||||
|
||||
|
@ -188,7 +188,7 @@ $ rails server
|
|||
=> Booting WEBrick...
|
||||
```
|
||||
|
||||
The URL will be "http://localhost:3000/greetings/hello":http://localhost:3000/greetings/hello.
|
||||
The URL will be [http://localhost:3000/greetings/hello](http://localhost:3000/greetings/hello).
|
||||
|
||||
INFO: With a normal, plain-old Rails application, your URLs will generally follow the pattern of http://(host)/(controller)/(action), and a URL like http://(host)/(controller) will hit the *index* action of that controller.
|
||||
|
||||
|
@ -211,7 +211,7 @@ Description:
|
|||
Create rails files for model generator.
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
But instead of generating a model directly (which we'll be doing later), let's set up a scaffold. A *scaffold* in Rails is a full set of model, database migration for that model, controller to manipulate it, views to view and manipulate the data, and a test suite for each of the above.
|
||||
|
||||
|
@ -270,7 +270,7 @@ Let's see the interface Rails created for us.
|
|||
$ rails server
|
||||
```
|
||||
|
||||
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!)
|
||||
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!)
|
||||
|
||||
### `rails console`
|
||||
|
||||
|
@ -392,7 +392,7 @@ You can precompile the assets in `app/assets` using `rake assets:precompile` and
|
|||
|
||||
The most common tasks of the `db:` Rake namespace are `migrate` and `create`, and it will pay off to try out all of the migration rake tasks (`up`, `down`, `redo`, `reset`). `rake db:version` is useful when troubleshooting, telling you the current version of the database.
|
||||
|
||||
More information about migrations can be found in the "Migrations":migrations.html guide.
|
||||
More information about migrations can be found in the [Migrations](migrations.html) guide.
|
||||
|
||||
### `doc`
|
||||
|
||||
|
@ -459,7 +459,7 @@ rspec/model/user_spec.rb:
|
|||
|
||||
### `test`
|
||||
|
||||
INFO: A good description of unit testing in Rails is given in "A Guide to Testing Rails Applications":testing.html
|
||||
INFO: A good description of unit testing in Rails is given in [A Guide to Testing Rails Applications](testing.html)
|
||||
|
||||
Rails comes with a test suite called `Test::Unit`. Rails owes its stability to the use of tests. The tasks available in the `test:` namespace helps in running the different tests you will hopefully write.
|
||||
|
||||
|
@ -484,7 +484,7 @@ The `tmp:` namespaced tasks will help you clear the `Rails.root/tmp` directory:
|
|||
|
||||
If you have (or want to write) any automation scripts outside your app (data import, checks, etc), you can make them as rake tasks. It's easy.
|
||||
|
||||
INFO: "Complete guide about how to write tasks":http://rake.rubyforge.org/files/doc/rakefile_rdoc.html is available in the official documentation.
|
||||
INFO: [Complete guide about how to write tasks](http://rake.rubyforge.org/files/doc/rakefile_rdoc.html) is available in the official documentation.
|
||||
|
||||
Tasks should be placed in `Rails.root/lib/tasks` and should have a `.rake` extension.
|
||||
|
||||
|
@ -596,7 +596,7 @@ NOTE. The only catch with using the SCM options is that you have to make your ap
|
|||
|
||||
Many people have created a large number of different web servers in Ruby, and many of them can be used to run Rails. Since version 2.3, Rails uses Rack to serve its webpages, which means that any webserver that implements a Rack handler can be used. This includes WEBrick, Mongrel, Thin, and Phusion Passenger (to name a few!).
|
||||
|
||||
NOTE: For more details on the Rack integration, see "Rails on Rack":rails_on_rack.html.
|
||||
NOTE: For more details on the Rack integration, see [Rails on Rack](rails_on_rack.html).
|
||||
|
||||
To use a different server, just install its gem, then use its name for the first parameter to `rails server`:
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ end
|
|||
|
||||
* `config.logger` accepts a logger conforming to the interface of Log4r or the default Ruby `Logger` class. Defaults to an instance of `ActiveSupport::BufferedLogger`, with auto flushing off in production mode.
|
||||
|
||||
* `config.middleware` allows you to configure the application's middleware. This is covered in depth in the "Configuring Middleware":#configuring-middleware section below.
|
||||
* `config.middleware` allows you to configure the application's middleware. This is covered in depth in the [Configuring Middleware](#configuring-middleware) section below.
|
||||
|
||||
* `config.queue` configures a different queue implementation for the application. Defaults to `ActiveSupport::SynchronousQueue`. Note that, if the default queue is changed, the default `queue_consumer` is not going to be initialized, it is up to the new queue implementation to handle starting and shutting down its own consumer(s).
|
||||
|
||||
|
@ -358,7 +358,7 @@ Proc.new { |html_tag, instance| %Q(<div class="field_with_errors">#{html_tag}</d
|
|||
|
||||
* `config.action_view.logger` accepts a logger conforming to the interface of Log4r or the default Ruby Logger class, which is then used to log information from Action View. Set to `nil` to disable logging.
|
||||
|
||||
* `config.action_view.erb_trim_mode` gives the trim mode to be used by ERB. It defaults to `'-'`. See the "ERB documentation":http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/ for more information.
|
||||
* `config.action_view.erb_trim_mode` gives the trim mode to be used by ERB. It defaults to `'-'`. See the [ERB documentation](http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/) for more information.
|
||||
|
||||
* `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:
|
||||
|
||||
|
@ -477,7 +477,7 @@ TIP: You don't have to update the database configurations manually. If you look
|
|||
|
||||
#### Configuring an SQLite3 Database
|
||||
|
||||
Rails comes with built-in support for "SQLite3":http://www.sqlite.org, which is a lightweight serverless database application. While a busy production environment may overload SQLite, it works well for development and testing. Rails defaults to using an SQLite database when creating a new project, but you can always change it later.
|
||||
Rails comes with built-in support for [SQLite3](http://www.sqlite.org), which is a lightweight serverless database application. While a busy production environment may overload SQLite, it works well for development and testing. Rails defaults to using an SQLite database when creating a new project, but you can always change it later.
|
||||
|
||||
Here's the section of the default configuration file (`config/database.yml`) with connection information for the development environment:
|
||||
|
||||
|
|
|
@ -16,13 +16,13 @@ Ruby on Rails is not "someone else's framework." Over the years, hundreds of peo
|
|||
Reporting an Issue
|
||||
------------------
|
||||
|
||||
Ruby on Rails uses "GitHub Issue Tracking":https://github.com/rails/rails/issues to track issues (primarily bugs and contributions of new code). If you've found a bug in Ruby on Rails, this is the place to start. You'll need to create a (free) GitHub account in order to submit an issue, to comment on them or to create pull requests.
|
||||
Ruby on Rails uses [GitHub Issue Tracking](https://github.com/rails/rails/issues) to track issues (primarily bugs and contributions of new code). If you've found a bug in Ruby on Rails, this is the place to start. You'll need to create a (free) GitHub account in order to submit an issue, to comment on them or to create pull requests.
|
||||
|
||||
NOTE: Bugs in the most recent released version of Ruby on Rails are likely to get the most attention. Also, the Rails core team is always interested in feedback from those who can take the time to test _edge Rails_ (the code for the version of Rails that is currently under development). Later in this guide you'll find out how to get edge Rails for testing.
|
||||
|
||||
### Creating a Bug Report
|
||||
|
||||
If you've found a problem in Ruby on Rails which is not a security risk, do a search in GitHub under "Issues":https://github.com/rails/rails/issues in case it was already reported. If you find no issue addressing it you can "add a new one":https://github.com/rails/rails/issues/new. (See the next section for reporting security issues.)
|
||||
If you've found a problem in Ruby on Rails which is not a security risk, do a search in GitHub under [Issues](https://github.com/rails/rails/issues in case it was already reported. If you find no issue addressing it you can [add a new one](https://github.com/rails/rails/issues/new). (See the next section for reporting security issues).
|
||||
|
||||
At the minimum, your issue report needs a title and descriptive text. But that's only a minimum. You should include as much relevant information as possible. You need at least to post the code sample that has the issue. Even better is to include a unit test that shows how the expected behavior is not occurring. Your goal should be to make it easy for yourself -- and others -- to replicate the bug and figure out a fix.
|
||||
|
||||
|
@ -30,13 +30,13 @@ Then, don't get your hopes up! Unless you have a "Code Red, Mission Critical, th
|
|||
|
||||
### Special Treatment for Security Issues
|
||||
|
||||
WARNING: Please do not report security vulnerabilities with public GitHub issue reports. The "Rails security policy page":http://rubyonrails.org/security details the procedure to follow for security issues.
|
||||
WARNING: Please do not report security vulnerabilities with public GitHub issue reports. The [Rails security policy page](http://rubyonrails.org/security) details the procedure to follow for security issues.
|
||||
|
||||
### What about Feature Requests?
|
||||
|
||||
Please don't put "feature request" items into GitHub Issues. If there's a new feature that you want to see added to Ruby on Rails, you'll need to write the code yourself - or convince someone else to partner with you to write the code. Later in this guide you'll find detailed instructions for proposing a patch to Ruby on Rails. If you enter a wishlist item in GitHub Issues with no code, you can expect it to be marked "invalid" as soon as it's reviewed.
|
||||
|
||||
If you'd like feedback on an idea for a feature before doing the work for make a patch, please send an email to the "rails-core mailing list":https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core. You might get no response, which means that everyone is indifferent. You might find someone who's also interested in building that feature. You might get a "This won't be accepted." But it's the proper place to discuss new ideas. GitHub Issues are not a particularly good venue for the sometimes long and involved discussions new features require.
|
||||
If you'd like feedback on an idea for a feature before doing the work for make a patch, please send an email to the [rails-core mailing list](https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core). You might get no response, which means that everyone is indifferent. You might find someone who's also interested in building that feature. You might get a "This won't be accepted." But it's the proper place to discuss new ideas. GitHub Issues are not a particularly good venue for the sometimes long and involved discussions new features require.
|
||||
|
||||
Setting Up a Development Environment
|
||||
------------------------------------
|
||||
|
@ -45,18 +45,18 @@ To move on from submitting bugs to helping resolve existing issues or contributi
|
|||
|
||||
### The Easy Way
|
||||
|
||||
The easiest way to get a development environment ready to hack is to use the "Rails development box":https://github.com/rails/rails-dev-box.
|
||||
The easiest way to get a development environment ready to hack is to use the [Rails development box](https://github.com/rails/rails-dev-box).
|
||||
|
||||
### The Hard Way
|
||||
|
||||
#### Install Git
|
||||
|
||||
Ruby on Rails uses Git for source code control. The "Git homepage":http://git-scm.com/ has installation instructions. There are a variety of resources on the net that will help you get familiar with Git:
|
||||
Ruby on Rails uses Git for source code control. The [Git homepage](http://git-scm.com/) has installation instructions. There are a variety of resources on the net that will help you get familiar with Git:
|
||||
|
||||
* "Everyday Git":http://schacon.github.com/git/everyday.html will teach you just enough about Git to get by.
|
||||
* The "PeepCode screencast":https://peepcode.com/products/git on Git ($9) is easier to follow.
|
||||
* "GitHub":http://help.github.com offers links to a variety of Git resources.
|
||||
* "Pro Git":http://git-scm.com/book is an entire book about Git with a Creative Commons license.
|
||||
* [Everyday Git](http://schacon.github.com/git/everyday.html) will teach you just enough about Git to get by.
|
||||
* The [PeepCode screencast](https://peepcode.com/products/git) on Git ($9) is easier to follow.
|
||||
* [GitHub](http://help.github.com) offers links to a variety of Git resources.
|
||||
* [Pro Git](http://git-scm.com/book) is an entire book about Git with a Creative Commons license.
|
||||
|
||||
#### Clone the Ruby on Rails Repository
|
||||
|
||||
|
@ -83,7 +83,7 @@ If you are on Fedora or CentOS, you can run
|
|||
$ sudo yum install libxml2 libxml2-devel libxslt libxslt-devel
|
||||
```
|
||||
|
||||
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 .
|
||||
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
|
||||
|
||||
|
@ -97,7 +97,7 @@ And if you are on Fedora or CentOS, you're done with
|
|||
$ sudo yum install sqlite3 sqlite3-devel
|
||||
```
|
||||
|
||||
Get a recent version of "Bundler":http://gembundler.com/:
|
||||
Get a recent version of [Bundler](http://gembundler.com/:)
|
||||
|
||||
```bash
|
||||
$ gem install bundler
|
||||
|
@ -260,12 +260,12 @@ $ git branch --track 3-0-stable origin/3-0-stable
|
|||
$ git checkout 3-0-stable
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
Helping to Resolve Existing Issues
|
||||
----------------------------------
|
||||
|
||||
As a next step beyond reporting issues, you can help the core team resolve existing issues. If you check the "Everyone's Issues":https://github.com/rails/rails/issues list in GitHub Issues, you'll find lots of issues already requiring attention. What can you do for these? Quite a bit, actually:
|
||||
As a next step beyond reporting issues, you can help the core team resolve existing issues. If you check the [Everyone's Issues](https://github.com/rails/rails/issues) list in GitHub Issues, you'll find lots of issues already requiring attention. What can you do for these? Quite a bit, actually:
|
||||
|
||||
### Verifying Bug Reports
|
||||
|
||||
|
@ -312,13 +312,13 @@ Contributing to the Rails Documentation
|
|||
|
||||
Ruby on Rails has two main sets of documentation: the guides help you in learning about Ruby on Rails, and the API is a reference.
|
||||
|
||||
You can help improve the Rails guides by making them more coherent, consistent or readable, adding missing information, correcting factual errors, fixing typos, or bringing it up to date with the latest edge Rails. To get involved in the translation of Rails guides, please see "Translating Rails Guides":https://wiki.github.com/lifo/docrails/translating-rails-guides.
|
||||
You can help improve the Rails guides by making them more coherent, consistent or readable, adding missing information, correcting factual errors, fixing typos, or bringing it up to date with the latest edge Rails. To get involved in the translation of Rails guides, please see [Translating Rails Guides](https://wiki.github.com/lifo/docrails/translating-rails-guides).
|
||||
|
||||
If you're confident about your changes, you can push them directly yourself via "docrails":https://github.com/lifo/docrails. Docrails is a branch with an *open commit policy* and public write access. Commits to docrails are still reviewed, but this happens after they are pushed. Docrails is merged with master regularly, so you are effectively editing the Ruby on Rails documentation.
|
||||
If you're confident about your changes, you can push them directly yourself via [docrails](https://github.com/lifo/docrails). Docrails is a branch with an *open commit policy* and public write access. Commits to docrails are still reviewed, but this happens after they are pushed. Docrails is merged with master regularly, so you are effectively editing the Ruby on Rails documentation.
|
||||
|
||||
If you are unsure of the documentation changes, you can create an issue in the "Rails":https://github.com/rails/rails/issues issues tracker on GitHub.
|
||||
If you are unsure of the documentation changes, you can create an issue in the [Rails](https://github.com/rails/rails/issues) issues tracker on GitHub.
|
||||
|
||||
When working with documentation, please take into account the "API Documentation Guidelines":api_documentation_guidelines.html and the "Ruby on Rails Guides Guidelines":ruby_on_rails_guides_guidelines.html.
|
||||
When working with documentation, please take into account the [API Documentation Guidelines](api_documentation_guidelines.html) and the [Ruby on Rails Guides Guidelines](ruby_on_rails_guides_guidelines.html).
|
||||
|
||||
NOTE: As explained earlier, ordinary code patches should have proper documentation coverage. Docrails is only used for isolated documentation improvements.
|
||||
|
||||
|
@ -401,7 +401,7 @@ Your name can be added directly after the last word if you don't provide any cod
|
|||
|
||||
You should not be the only person who looks at the code before you submit it. You know at least one other Rails developer, right? Show them what you’re doing and ask for feedback. Doing this in private before you push a patch out publicly is the “smoke test” for a patch: if you can’t convince one other developer of the beauty of your code, you’re unlikely to convince the core team either.
|
||||
|
||||
You might want also to check out the "RailsBridge BugMash":http://wiki.railsbridge.org/projects/railsbridge/wiki/BugMash as a way to get involved in a group effort to improve Rails. This can help you get started and help you check your code when you're writing your first patches.
|
||||
You might want also to check out the [RailsBridge BugMash](http://wiki.railsbridge.org/projects/railsbridge/wiki/BugMash) as a way to get involved in a group effort to improve Rails. This can help you get started and help you check your code when you're writing your first patches.
|
||||
|
||||
### Commit Your Changes
|
||||
|
||||
|
@ -463,7 +463,7 @@ No conflicts? Tests still pass? Change still seems reasonable to you? Then move
|
|||
|
||||
### Fork
|
||||
|
||||
Navigate to the Rails "GitHub repository":https://github.com/rails/rails and press "Fork" in the upper right hand corner.
|
||||
Navigate to the Rails [GitHub repository](https://github.com/rails/rails) and press "Fork" in the upper right hand corner.
|
||||
|
||||
Add the new remote to your local repository on your local machine:
|
||||
|
||||
|
@ -525,7 +525,7 @@ Fill in some details about your potential patch including a meaningful title. Wh
|
|||
|
||||
### Get some Feedback
|
||||
|
||||
Now you need to get other people to look at your patch, just as you've looked at other people's patches. You can use the "rubyonrails-core mailing list":http://groups.google.com/group/rubyonrails-core/ or the #rails-contrib channel on IRC freenode for this. You might also try just talking to Rails developers that you know.
|
||||
Now you need to get other people to look at your patch, just as you've looked at other people's patches. You can use the [rubyonrails-core mailing list](http://groups.google.com/group/rubyonrails-core/) or the #rails-contrib channel on IRC freenode for this. You might also try just talking to Rails developers that you know.
|
||||
|
||||
### Iterate as Necessary
|
||||
|
||||
|
@ -535,7 +535,7 @@ It’s entirely possible that the feedback you get will suggest changes. Don’t
|
|||
|
||||
Changes that are merged into master are intended for the next major release of Rails. Sometimes, it might be beneficial for your changes to propagate back to the maintenance releases for older stable branches. Generally, security fixes and bug fixes are good candidates for a backport, while new features and patches that introduce a change in behavior will not be accepted. When in doubt, it is best to consult a Rails team member before backporting your changes to avoid wasted effort.
|
||||
|
||||
For simple fixes, the easiest way to backport your changes is to "extract a diff from your changes in master and apply them to the target branch":http://ariejan.net/2009/10/26/how-to-create-and-apply-a-patch-with-git.
|
||||
For simple fixes, the easiest way to backport your changes is to [extract a diff from your changes in master and apply them to the target branch](http://ariejan.net/2009/10/26/how-to-create-and-apply-a-patch-with-git).
|
||||
|
||||
First make sure your changes are the only difference between your current branch and master:
|
||||
|
||||
|
@ -565,4 +565,4 @@ And then... think about your next contribution!
|
|||
Rails Contributors
|
||||
------------------
|
||||
|
||||
All contributions, either via master or docrails, get credit in "Rails Contributors":http://contributors.rubyonrails.org.
|
||||
All contributions, either via master or docrails, get credit in [Rails Contributors](http://contributors.rubyonrails.org).
|
||||
|
|
|
@ -642,7 +642,7 @@ In this section, you will learn how to find and fix such leaks by using tools su
|
|||
|
||||
### BleakHouse
|
||||
|
||||
"BleakHouse":https://github.com/evan/bleak_house/ is a library for finding memory leaks.
|
||||
[BleakHouse](https://github.com/evan/bleak_house/) is a library for finding memory leaks.
|
||||
|
||||
If a Ruby object does not go out of scope, the Ruby Garbage Collector won't sweep it since it is referenced somewhere. Leaks like this can grow slowly and your application will consume more and more memory, gradually affecting the overall system performance. This tool will help you find leaks on the Ruby heap.
|
||||
|
||||
|
@ -691,39 +691,39 @@ To analyze it, just run the listed command. The top 20 leakiest lines will be li
|
|||
|
||||
This way you can find where your application is leaking memory and fix it.
|
||||
|
||||
If "BleakHouse":https://github.com/evan/bleak_house/ doesn't report any heap growth but you still have memory growth, you might have a broken C extension, or real leak in the interpreter. In that case, try using Valgrind to investigate further.
|
||||
If [BleakHouse](https://github.com/evan/bleak_house/) doesn't report any heap growth but you still have memory growth, you might have a broken C extension, or real leak in the interpreter. In that case, try using Valgrind to investigate further.
|
||||
|
||||
### Valgrind
|
||||
|
||||
"Valgrind":http://valgrind.org/ is a Linux-only application for detecting C-based memory leaks and race conditions.
|
||||
[Valgrind](http://valgrind.org/) is a Linux-only application for detecting C-based memory leaks and race conditions.
|
||||
|
||||
There are Valgrind tools that can automatically detect many memory management and threading bugs, and profile your programs in detail. For example, a C extension in the interpreter calls `malloc()` but is doesn't properly call `free()`, this memory won't be available until the app terminates.
|
||||
|
||||
For further information on how to install Valgrind and use with Ruby, refer to "Valgrind and Ruby":http://blog.evanweaver.com/articles/2008/02/05/valgrind-and-ruby/ by Evan Weaver.
|
||||
For further information on how to install Valgrind and use with Ruby, refer to [Valgrind and Ruby](http://blog.evanweaver.com/articles/2008/02/05/valgrind-and-ruby/) by Evan Weaver.
|
||||
|
||||
Plugins for Debugging
|
||||
---------------------
|
||||
|
||||
There are some Rails plugins to help you to find errors and debug your application. Here is a list of useful plugins for debugging:
|
||||
|
||||
* "Footnotes":https://github.com/josevalim/rails-footnotes: Every Rails page has footnotes that give request information and link back to your source via TextMate.
|
||||
* "Query Trace":https://github.com/ntalbott/query_trace/tree/master: Adds query origin tracing to your logs.
|
||||
* "Query Stats":https://github.com/dan-manges/query_stats/tree/master: A Rails plugin to track database queries.
|
||||
* "Query Reviewer":http://code.google.com/p/query-reviewer/: This rails plugin not only runs "EXPLAIN" before each of your select queries in development, but provides a small DIV in the rendered output of each page with the summary of warnings for each query that it analyzed.
|
||||
* "Exception Notifier":https://github.com/smartinez87/exception_notification/tree/master: Provides a mailer object and a default set of templates for sending email notifications when errors occur in a Rails application.
|
||||
* "Exception Logger":https://github.com/defunkt/exception_logger/tree/master: Logs your Rails exceptions in the database and provides a funky web interface to manage them.
|
||||
* [Footnotes](https://github.com/josevalim/rails-footnotes:) Every Rails page has footnotes that give request information and link back to your source via TextMate.
|
||||
* [Query Trace](https://github.com/ntalbott/query_trace/tree/master:) Adds query origin tracing to your logs.
|
||||
* [Query Stats](https://github.com/dan-manges/query_stats/tree/master:) A Rails plugin to track database queries.
|
||||
* [Query Reviewer](http://code.google.com/p/query-reviewer/:) This rails plugin not only runs "EXPLAIN" before each of your select queries in development, but provides a small DIV in the rendered output of each page with the summary of warnings for each query that it analyzed.
|
||||
* [Exception Notifier](https://github.com/smartinez87/exception_notification/tree/master:) Provides a mailer object and a default set of templates for sending email notifications when errors occur in a Rails application.
|
||||
* [Exception Logger](https://github.com/defunkt/exception_logger/tree/master:) Logs your Rails exceptions in the database and provides a funky web interface to manage them.
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
* "ruby-debug Homepage":http://bashdb.sourceforge.net/ruby-debug/home-page.html
|
||||
* "debugger Homepage":http://github.com/cldwalker/debugger
|
||||
* "Article: Debugging a Rails application with ruby-debug":http://www.sitepoint.com/article/debug-rails-app-ruby-debug/
|
||||
* "ruby-debug Basics screencast":http://brian.maybeyoureinsane.net/blog/2007/05/07/ruby-debug-basics-screencast/
|
||||
* "Ryan Bates' debugging ruby (revised) screencast":http://railscasts.com/episodes/54-debugging-ruby-revised
|
||||
* "Ryan Bates' stack trace screencast":http://railscasts.com/episodes/24-the-stack-trace
|
||||
* "Ryan Bates' logger screencast":http://railscasts.com/episodes/56-the-logger
|
||||
* "Debugging with ruby-debug":http://bashdb.sourceforge.net/ruby-debug.html
|
||||
* "ruby-debug cheat sheet":http://cheat.errtheblog.com/s/rdebug/
|
||||
* "Ruby on Rails Wiki: How to Configure Logging":http://wiki.rubyonrails.org/rails/pages/HowtoConfigureLogging
|
||||
* "Bleak House Documentation":http://blog.evanweaver.com/files/doc/fauna/bleak_house/
|
||||
* [ruby-debug Homepage](http://bashdb.sourceforge.net/ruby-debug/home-page.html)
|
||||
* [debugger Homepage](http://github.com/cldwalker/debugger)
|
||||
* [Article: Debugging a Rails application with ruby-debug](http://www.sitepoint.com/article/debug-rails-app-ruby-debug/)
|
||||
* [ruby-debug Basics screencast](http://brian.maybeyoureinsane.net/blog/2007/05/07/ruby-debug-basics-screencast/)
|
||||
* [Ryan Bates' debugging ruby (revised) screencast](http://railscasts.com/episodes/54-debugging-ruby-revised)
|
||||
* [Ryan Bates' stack trace screencast](http://railscasts.com/episodes/24-the-stack-trace)
|
||||
* [Ryan Bates' logger screencast](http://railscasts.com/episodes/56-the-logger)
|
||||
* [Debugging with ruby-debug](http://bashdb.sourceforge.net/ruby-debug.html)
|
||||
* [ruby-debug cheat sheet](http://cheat.errtheblog.com/s/rdebug/)
|
||||
* [Ruby on Rails Wiki: How to Configure Logging](http://wiki.rubyonrails.org/rails/pages/HowtoConfigureLogging)
|
||||
* [Bleak House Documentation](http://blog.evanweaver.com/files/doc/fauna/bleak_house/)
|
||||
|
|
|
@ -26,7 +26,7 @@ Engines can also be isolated from their host applications. This means that an ap
|
|||
|
||||
It's important to keep in mind at all times that the application should *always* take precedence over its engines. An application is the object that has final say in what goes on in the universe (with the universe being the application's environment) where the engine should only be enhancing it, rather than changing it drastically.
|
||||
|
||||
To see demonstrations of other engines, check out "Devise":https://github.com/plataformatec/devise, an engine that provides authentication for its parent applications, or "Forem":https://github.com/radar/forem, an engine that provides forum functionality. There's also "Spree":https://github.com/spree/spree which provides an e-commerce platform, and "RefineryCMS":https://github.com/resolve/refinerycms, a CMS engine.
|
||||
To see demonstrations of other engines, check out [Devise](https://github.com/plataformatec/devise), an engine that provides authentication for its parent applications, or [Forem](https://github.com/radar/forem), an engine that provides forum functionality. There's also [Spree](https://github.com/spree/spree) which provides an e-commerce platform, and [RefineryCMS](https://github.com/resolve/refinerycms), a CMS engine.
|
||||
|
||||
Finally, engines would not have been possible without the work of James Adam, Piotr Sarnacki, the Rails Core Team, and a number of other people. If you ever meet them, don't forget to say thanks!
|
||||
|
||||
|
@ -92,7 +92,7 @@ NOTE: It is *highly* recommended that the `isolate_namespace` line be left withi
|
|||
|
||||
What this isolation of the namespace means is that a model generated by a call to `rails g model` such as `rails g model post` won't be called `Post`, but instead be namespaced and called `Blorgh::Post`. In addition, the table for the model is namespaced, becoming `blorgh_posts`, rather than simply `posts`. Similar to the model namespacing, a controller called `PostsController` becomes `Blorgh::PostsController` and the views for that controller will not be at `app/views/posts`, but `app/views/blorgh/posts` instead. Mailers are namespaced as well.
|
||||
|
||||
Finally, routes will also be isolated within the engine. This is one of the most important parts about namespacing, and is discussed later in the "Routes":#routes section of this guide.
|
||||
Finally, routes will also be isolated within the engine. This is one of the most important parts about namespacing, and is discussed later in the [Routes](#routes) section of this guide.
|
||||
|
||||
#### `app` directory
|
||||
|
||||
|
@ -135,7 +135,7 @@ Also in the test directory is the `test/integration` directory, where integratio
|
|||
Providing engine functionality
|
||||
------------------------------
|
||||
|
||||
The engine that this guide covers provides posting and commenting functionality and follows a similar thread to the "Getting Started Guide":getting_started.html, with some new twists.
|
||||
The engine that this guide covers provides posting and commenting functionality and follows a similar thread to the [Getting Started Guide](getting_started.html), with some new twists.
|
||||
|
||||
### Generating a post resource
|
||||
|
||||
|
@ -191,7 +191,7 @@ Blorgh::Engine.routes.draw do
|
|||
end
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
Next, the `scaffold_controller` generator is invoked, generating a controller called `Blorgh::PostsController` (at `app/controllers/blorgh/posts_controller.rb`) and its related views at `app/views/blorgh/posts`. This generator also generates a functional test for the controller (`test/functional/blorgh/posts_controller_test.rb`) and a helper (`app/helpers/blorgh/posts_controller.rb`).
|
||||
|
||||
|
@ -626,7 +626,7 @@ There are now no strict dependencies on what the class is, only what the API for
|
|||
|
||||
Within an engine, there may come a time where you wish to use things such as initializers, internationalization or other configuration options. The great news is that these things are entirely possible because a Rails engine shares much the same functionality as a Rails application. In fact, a Rails application's functionality is actually a superset of what is provided by engines!
|
||||
|
||||
If you wish to use an initializer -- code that should run before the engine is loaded -- the place for it is the `config/initializers` folder. This directory's functionality is explained in the "Initializers section":http://guides.rubyonrails.org/configuring.html#initializers of the Configuring guide, and works precisely the same way as the `config/initializers` directory inside an application. Same goes for if you want to use a standard initializer.
|
||||
If you wish to use an initializer -- code that should run before the engine is loaded -- the place for it is the `config/initializers` folder. This directory's functionality is explained in the [Initializers section](http://guides.rubyonrails.org/configuring.html#initializers) of the Configuring guide, and works precisely the same way as the `config/initializers` directory inside an application. Same goes for if you want to use a standard initializer.
|
||||
|
||||
For locales, simply place the locale files in the `config/locales` directory, just like you would in an application.
|
||||
|
||||
|
@ -713,7 +713,7 @@ end
|
|||
|
||||
#### Implementing Decorator Pattern Using ActiveSupport::Concern
|
||||
|
||||
Using `Class#class_eval` is great for simple adjustments, but for more complex class modifications, you might want to consider using `ActiveSupport::Concern`. ["**ActiveSupport::Concern**":http://edgeapi.rubyonrails.org/classes/ActiveSupport/Concern.html] helps manage the load order of interlinked dependencies at run time allowing you to significantly modularize your code.
|
||||
Using `Class#class_eval` is great for simple adjustments, but for more complex class modifications, you might want to consider using `ActiveSupport::Concern`. [[**ActiveSupport::Concern**](http://edgeapi.rubyonrails.org/classes/ActiveSupport/Concern.html]) helps manage load order of interlinked dependencies at run time allowing you to significantly modularize your code.
|
||||
|
||||
**Adding** `Post#time_since_created`<br/>
|
||||
**Overriding** `Post#summary`
|
||||
|
@ -870,7 +870,7 @@ initializer "blorgh.assets.precompile" do |app|
|
|||
end
|
||||
```
|
||||
|
||||
For more information, read the "Asset Pipeline guide":http://guides.rubyonrails.org/asset_pipeline.html
|
||||
For more information, read the [Asset Pipeline guide](http://guides.rubyonrails.org/asset_pipeline.html)
|
||||
|
||||
### Other gem dependencies
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ In this guide you will:
|
|||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
NOTE: This guide is not intended to be a complete documentation of available form helpers and their arguments. Please visit "the Rails API documentation":http://api.rubyonrails.org/ for a complete reference.
|
||||
NOTE: This guide is not intended to be a complete documentation of available form helpers and their arguments. Please visit [the Rails API documentation](http://api.rubyonrails.org/) for a complete reference.
|
||||
|
||||
|
||||
Dealing with Basic Forms
|
||||
|
@ -41,7 +41,7 @@ When called without arguments like this, it creates a `<form>` tag which,
|
|||
</form>
|
||||
```
|
||||
|
||||
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.
|
||||
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).
|
||||
|
||||
NOTE: Throughout this guide, the `div` with the hidden input elements will be excluded from code samples for brevity.
|
||||
|
||||
|
@ -102,7 +102,7 @@ form_tag({:controller => "people", :action => "search"}, :method => "get", :clas
|
|||
|
||||
Rails provides a series of helpers for generating form elements such as checkboxes, text fields, and radio buttons. These basic helpers, with names ending in "_tag" (such as `text_field_tag` and `check_box_tag`), generate just a single `<input>` element. The first parameter to these is always the name of the input. When the form is submitted, the name will be passed along with the form data, and will make its way to the `params` hash in the controller with the value entered by the user for that field. For example, if the form contains `<%= text_field_tag(:query) %>`, then you would be able to get the value of this field in the controller with `params[:query]`.
|
||||
|
||||
When naming inputs, Rails uses certain conventions that make it possible to submit parameters with non-scalar values such as arrays or hashes, which will also be accessible in `params`. You can read more about them in "chapter 7 of this guide":#understanding-parameter-naming-conventions. For details on the precise usage of these helpers, please refer to the "API documentation":http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html.
|
||||
When naming inputs, Rails uses certain conventions that make it possible to submit parameters with non-scalar values such as arrays or hashes, which will also be accessible in `params`. You can read more about them in [chapter 7 of this guide](#understanding-parameter-naming-conventions). For details on the precise usage of these helpers, please refer to the [API documentation](http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html).
|
||||
|
||||
#### Checkboxes
|
||||
|
||||
|
@ -192,9 +192,9 @@ Output:
|
|||
|
||||
Hidden inputs are not shown to the user but instead hold data like any textual input. Values inside them can be changed with JavaScript.
|
||||
|
||||
IMPORTANT: The search, telephone, date, time, color, datetime, datetime-local, month, week, URL, and email inputs are HTML5 controls. If you require your app to have a consistent experience in older browsers, you will need an HTML5 polyfill (provided by CSS and/or JavaScript). There is definitely "no shortage of solutions for this":https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills, although a couple of popular tools at the moment are "Modernizr":http://www.modernizr.com/ and "yepnope":http://yepnopejs.com/, which provide a simple way to add functionality based on the presence of detected HTML5 features.
|
||||
IMPORTANT: The search, telephone, date, time, color, datetime, datetime-local, month, week, URL, and email inputs are HTML5 controls. If you require your app to have a consistent experience in older browsers, you will need an HTML5 polyfill (provided by CSS and/or JavaScript). There is definitely [no shortage of solutions for this](https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills), although a couple of popular tools at the moment are [Modernizr](http://www.modernizr.com/) and [yepnope](http://yepnopejs.com/), which provide a simple way to add functionality based on the presence of detected HTML5 features.
|
||||
|
||||
TIP: If you're using password input fields (for any purpose), you might want to configure your application to prevent those parameters from being logged. You can learn about this in the "Security Guide":security.html#logging.
|
||||
TIP: If you're using password input fields (for any purpose), you might want to configure your application to prevent those parameters from being logged. You can learn about this in the [Security Guide](security.html#logging).
|
||||
|
||||
Dealing with Model Objects
|
||||
--------------------------
|
||||
|
@ -219,7 +219,7 @@ Upon form submission the value entered by the user will be stored in `params[:pe
|
|||
|
||||
WARNING: You must pass the name of an instance variable, i.e. `:person` or `"person"`, not an actual instance of your model object.
|
||||
|
||||
Rails provides helpers for displaying the validation errors associated with a model object. These are covered in detail by the "Active Record Validations and Callbacks":./active_record_validations_callbacks.html#displaying-validation-errors-in-the-view guide.
|
||||
Rails provides helpers for displaying the validation errors associated with a model object. These are covered in detail by the [Active Record Validations and Callbacks](./active_record_validations_callbacks.html#displaying-validation-errors-in-the-view) guide.
|
||||
|
||||
### Binding a Form to an Object
|
||||
|
||||
|
@ -294,7 +294,7 @@ The Article model is directly available to users of the application, so -- follo
|
|||
resources :articles
|
||||
```
|
||||
|
||||
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.
|
||||
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:
|
||||
|
||||
|
@ -332,7 +332,7 @@ will create a form that submits to the articles controller inside the admin name
|
|||
form_for [:admin, :management, @article]
|
||||
```
|
||||
|
||||
For more information on Rails' routing system and the associated conventions, please see the "routing guide":routing.html.
|
||||
For more information on Rails' routing system and the associated conventions, please see the [routing guide](routing.html).
|
||||
|
||||
|
||||
### How do forms with PATCH, PUT, or DELETE methods work?
|
||||
|
@ -458,7 +458,7 @@ As with other helpers, if you were to use the `select` helper on a form builder
|
|||
<%= f.select(:city_id, ...) %>
|
||||
```
|
||||
|
||||
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 ` ActiveRecord::AssociationTypeMismatch: City(#17815740) expected, got String(#1138750) ` 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.
|
||||
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 ` ActiveRecord::AssociationTypeMismatch: City(#17815740) expected, got String(#1138750) ` 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).
|
||||
|
||||
### Option Tags from a Collection of Arbitrary Objects
|
||||
|
||||
|
@ -495,7 +495,7 @@ To leverage time zone support in Rails, you have to ask your users what time zon
|
|||
|
||||
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.
|
||||
|
||||
Rails _used_ to have a `country_select` helper for choosing countries, but this has been extracted to the "country_select plugin":https://github.com/chrislerum/country_select. When using this, be aware that the exclusion or inclusion of certain names from the list can be somewhat controversial (and was the reason this functionality was extracted from Rails).
|
||||
Rails _used_ to have a `country_select` helper for choosing countries, but this has been extracted to the [country_select plugin](https://github.com/chrislerum/country_select). When using this, be aware that the exclusion or inclusion of certain names from the list can be somewhat controversial (and was the reason this functionality was extracted from Rails).
|
||||
|
||||
Using Date and Time Form Helpers
|
||||
--------------------------------
|
||||
|
@ -558,7 +558,7 @@ When this is passed to `Person.new` (or `update_attributes`), Active Record spot
|
|||
|
||||
### Common Options
|
||||
|
||||
Both families of helpers use the same core set of functions to generate the individual select tags and so both accept largely the same options. In particular, by default Rails will generate year options 5 years either side of the current year. If this is not an appropriate range, the `:start_year` and `:end_year` options override this. For an exhaustive list of the available options, refer to the "API documentation":http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html.
|
||||
Both families of helpers use the same core set of functions to generate the individual select tags and so both accept largely the same options. In particular, by default Rails will generate year options 5 years either side of the current year. If this is not an appropriate range, the `:start_year` and `:end_year` options override this. For an exhaustive list of the available options, refer to the [API documentation](http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html).
|
||||
|
||||
As a rule of thumb you should be using `date_select` when working with model objects and `select_date` in other cases, such as a search form which filters results by date.
|
||||
|
||||
|
@ -611,7 +611,7 @@ def upload
|
|||
end
|
||||
```
|
||||
|
||||
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.
|
||||
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).
|
||||
|
||||
NOTE: If the user has not selected a file the corresponding parameter will be an empty string.
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ $ rails generate helper --help
|
|||
Creating Your First Generator
|
||||
-----------------------------
|
||||
|
||||
Since Rails 3.0, generators are built on top of "Thor":https://github.com/wycats/thor. Thor provides powerful options parsing and a great API for manipulating files. For instance, let's build a generator that creates an initializer file named `initializer.rb` inside `config/initializers`.
|
||||
Since Rails 3.0, generators are built on top of [Thor](https://github.com/wycats/thor). Thor provides powerful options parsing and a great API for manipulating files. For instance, let's build a generator that creates an initializer file named `initializer.rb` inside `config/initializers`.
|
||||
|
||||
The first step is to create a file at `lib/generators/initializer_generator.rb` with the following content:
|
||||
|
||||
|
@ -49,7 +49,7 @@ class InitializerGenerator < Rails::Generators::Base
|
|||
end
|
||||
```
|
||||
|
||||
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
|
||||
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)
|
||||
|
||||
Our new generator is quite simple: it inherits from `Rails::Generators::Base` and has one method definition. When a generator is invoked, each public method in the generator is executed sequentially in the order that it is defined. Finally, we invoke the `create_file` method that will create a file at the given destination with the given content. If you are familiar with the Rails Application Templates API, you'll feel right at home with the new generators API.
|
||||
|
||||
|
@ -137,7 +137,7 @@ $ rails generate initializer core_extensions
|
|||
|
||||
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`.
|
||||
|
||||
The methods that are available for generators are covered in the "final section":#generator-methods of this guide.
|
||||
The methods that are available for generators are covered in the [final section](#generator-methods) of this guide.
|
||||
|
||||
Generators Lookup
|
||||
-----------------
|
||||
|
@ -326,7 +326,7 @@ If you generate another resource, you can see that we get exactly the same resul
|
|||
Adding Generators Fallbacks
|
||||
---------------------------
|
||||
|
||||
One last feature about generators which is quite useful for plugin generators is fallbacks. For example, imagine that you want to add a feature on top of TestUnit like "shoulda":https://github.com/thoughtbot/shoulda does. Since TestUnit already implements all generators required by Rails and shoulda just wants to overwrite part of it, there is no need for shoulda to reimplement some generators again, it can simply tell Rails to use a `TestUnit` generator if none was found under the `Shoulda` namespace.
|
||||
One last feature about generators which is quite useful for plugin generators is fallbacks. For example, imagine that you want to add a feature on top of TestUnit like [shoulda](https://github.com/thoughtbot/shoulda) does. Since TestUnit already implements all generators required by Rails and shoulda just wants to overwrite part of it, there is no need for shoulda to reimplement some generators again, it can simply tell Rails to use a `TestUnit` generator if none was found under the `Shoulda` namespace.
|
||||
|
||||
We can easily simulate this behavior by changing our `config/application.rb` once again:
|
||||
|
||||
|
@ -414,7 +414,7 @@ Generator methods
|
|||
|
||||
The following are methods available for both generators and templates for Rails.
|
||||
|
||||
NOTE: Methods provided by Thor are not covered this guide and can be found in "Thor's documentation":http://rdoc.info/github/wycats/thor/master/Thor/Actions.html
|
||||
NOTE: Methods provided by Thor are not covered this guide and can be found in [Thor's documentation](http://rdoc.info/github/wycats/thor/master/Thor/Actions.html)
|
||||
|
||||
### `gem`
|
||||
|
||||
|
|
|
@ -22,20 +22,20 @@ application from scratch. It does not assume that you have any prior experience
|
|||
with Rails. However, to get the most out of it, you need to have some
|
||||
prerequisites installed:
|
||||
|
||||
* The "Ruby":http://www.ruby-lang.org/en/downloads language version 1.9.3 or higher
|
||||
* The [Ruby](http://www.ruby-lang.org/en/downloads) language version 1.9.3 or higher
|
||||
|
||||
* The "RubyGems":http://rubyforge.org/frs/?group_id=126 packaging system
|
||||
** If you want to learn more about RubyGems, please read the "RubyGems User Guide":http://docs.rubygems.org/read/book/1
|
||||
* A working installation of the "SQLite3 Database":http://www.sqlite.org
|
||||
* The [RubyGems](http://rubyforge.org/frs/?group_id=126) packaging system
|
||||
** If you want to learn more about RubyGems, please read the [RubyGems User Guide](http://docs.rubygems.org/read/book/1)
|
||||
* A working installation of the [SQLite3 Database](http://www.sqlite.org)
|
||||
|
||||
Rails is a web application framework running on the Ruby programming language.
|
||||
If you have no prior experience with Ruby, you will find a very steep learning
|
||||
curve diving straight into Rails. There are some good free resources on the
|
||||
internet for learning Ruby, including:
|
||||
|
||||
* "Mr. Neighborly's Humble Little Ruby Book":http://www.humblelittlerubybook.com
|
||||
* "Programming Ruby":http://www.ruby-doc.org/docs/ProgrammingRuby/
|
||||
* "Why's (Poignant) Guide to Ruby":http://mislav.uniqpath.com/poignant-guide/
|
||||
* [Mr. Neighborly's Humble Little Ruby Book](http://www.humblelittlerubybook.com)
|
||||
* [Programming Ruby](http://www.ruby-doc.org/docs/ProgrammingRuby/)
|
||||
* [Why's (Poignant) Guide to Ruby](http://mislav.uniqpath.com/poignant-guide/)
|
||||
|
||||
What is Rails?
|
||||
--------------
|
||||
|
@ -66,7 +66,7 @@ Creating a New Rails Project
|
|||
The best way to use this guide is to follow each step as it happens, no code or
|
||||
step needed to make this example application has been left out, so you can
|
||||
literally follow along step by step. You can get the complete code
|
||||
"here":https://github.com/lifo/docrails/tree/master/guides/code/getting_started.
|
||||
[here](https://github.com/lifo/docrails/tree/master/guides/code/getting_started).
|
||||
|
||||
By following along with this guide, you'll create a Rails project called
|
||||
`blog`, a
|
||||
|
@ -86,7 +86,7 @@ To install Rails, use the `gem install` command provided by RubyGems:
|
|||
TIP. A number of tools exist to help you quickly install Ruby and Ruby
|
||||
on Rails on your system. Windows users can use "Rails
|
||||
Installer":http://railsinstaller.org, while Mac OS X users can use
|
||||
"Rails One Click":http://railsoneclick.com.
|
||||
[Rails One Click](http://railsoneclick.com).
|
||||
|
||||
To verify that you have everything installed correctly, you should be able to run the following:
|
||||
|
||||
|
@ -124,18 +124,18 @@ application. Most of the work in this tutorial will happen in the `app/` folder,
|
|||
|
||||
|_.File/Folder|_.Purpose|
|
||||
|app/|Contains the controllers, models, views, helpers, mailers and assets for your application. You'll focus on this folder for the remainder of this guide.|
|
||||
|config/|Configure your application's runtime rules, routes, database, and more. This is covered in more detail in "Configuring Rails Applications":configuring.html|
|
||||
|config/|Configure your application's runtime rules, routes, database, and more. This is covered in more detail in [Configuring Rails Applications](configuring.html|)
|
||||
|config.ru|Rack configuration for Rack based servers used to start the application.|
|
||||
|db/|Contains your current database schema, as well as the database migrations.|
|
||||
|doc/|In-depth documentation for your application.|
|
||||
|Gemfile<br />Gemfile.lock|These files allow you to specify what gem dependencies are needed for your Rails application. These files are used by the Bundler gem. For more information about Bundler, see "the Bundler website":http://gembundler.com |
|
||||
|Gemfile<br />Gemfile.lock|These files allow you to specify what gem dependencies are needed for your Rails application. These files are used by the Bundler gem. For more information about Bundler, see [the Bundler website](http://gembundler.com) |
|
||||
|lib/|Extended modules for your application.|
|
||||
|log/|Application log files.|
|
||||
|public/|The only folder seen to the world as-is. Contains the static files and compiled assets.|
|
||||
|Rakefile|This file locates and loads tasks that can be run from the command line. The task definitions are defined throughout the components of Rails. Rather than changing Rakefile, you should add your own tasks by adding files to the lib/tasks directory of your application.|
|
||||
|README.rdoc|This is a brief instruction manual for your application. You should edit this file to tell others what your application does, how to set it up, and so on.|
|
||||
|script/|Contains the rails script that starts your app and can contain other scripts you use to deploy or run your application.|
|
||||
|test/|Unit tests, fixtures, and other test apparatus. These are covered in "Testing Rails Applications":testing.html|
|
||||
|test/|Unit tests, fixtures, and other test apparatus. These are covered in [Testing Rails Applications](testing.html|)
|
||||
|tmp/|Temporary files (like cache, pid and session files)|
|
||||
|vendor/|A place for all third-party code. In a typical Rails application, this includes Ruby Gems and the Rails source code (if you optionally install it into your project).|
|
||||
|
||||
|
@ -152,9 +152,9 @@ You actually have a functional Rails application already. To see it, you need to
|
|||
$ rails server
|
||||
```
|
||||
|
||||
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.
|
||||
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).
|
||||
|
||||
This will fire up WEBrick, a webserver built into Ruby by default. To see your application in action, open a browser window and navigate to "http://localhost:3000":http://localhost:3000. You should see the Rails default information page:
|
||||
This will fire up WEBrick, a webserver built into Ruby by default. To see your application in action, open a browser window and navigate to [http://localhost:3000](http://localhost:3000). You should see the Rails default information page:
|
||||
|
||||
!images/rails_welcome.png(Welcome Aboard screenshot)!
|
||||
|
||||
|
@ -207,7 +207,7 @@ Open the `app/views/welcome/index.html.erb` file in your text editor and edit it
|
|||
|
||||
### Setting the Application Home Page
|
||||
|
||||
Now that we have made the controller and view, we need to tell Rails when we want "Hello Rails!" to show up. In our case, we want it to show up when we navigate to the root URL of our site, "http://localhost:3000":http://localhost:3000. At the moment, however, the "Welcome Aboard" smoke test is occupying that spot.
|
||||
Now that we have made the controller and view, we need to tell Rails when we want [Hello Rails!" to show up. In our case, we want it to show up when we navigate to the root URL of our site, "http://localhost:3000](http://localhost:3000). At the moment, however, the "Welcome Aboard" smoke test is occupying that spot.
|
||||
|
||||
To fix this, delete the `index.html` file located inside the `public` directory of the application.
|
||||
|
||||
|
@ -235,11 +235,11 @@ This is your application's _routing file_ which holds entries in a special DSL (
|
|||
root :to => "welcome#index"
|
||||
```
|
||||
|
||||
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`).
|
||||
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`).
|
||||
|
||||
If you navigate to "http://localhost:3000":http://localhost:3000 in your browser, you'll see the `Hello, Rails!` message you put into `app/views/welcome/index.html.erb`, indicating that this new route is indeed going to `WelcomeController`'s `index` action and is rendering the view correctly.
|
||||
If you navigate to [http://localhost:3000](http://localhost:3000) in your browser, you'll see the `Hello, Rails!` message you put into `app/views/welcome/index.html.erb`, indicating that this new route is indeed going to `WelcomeController`'s `index` action and is rendering the view correctly.
|
||||
|
||||
NOTE. For more information about routing, refer to "Rails Routing from the Outside In":routing.html.
|
||||
NOTE. For more information about routing, refer to [Rails Routing from the Outside In](routing.html).
|
||||
|
||||
Getting Up and Running
|
||||
----------------------
|
||||
|
@ -256,7 +256,7 @@ It will look a little basic for now, but that's ok. We'll look at improving the
|
|||
|
||||
### Laying down the ground work
|
||||
|
||||
The first thing that you are going to need to create a new post within the application is a place to do that. A great place for that would be at `/posts/new`. If you attempt to navigate to that now -- by visiting "http://localhost:3000/posts/new":http://localhost:3000/posts/new -- Rails will give you a routing error:
|
||||
The first thing that you are going to need to create a new post within the application is a place to do that. A great place for that would be at `/posts/new`. If you attempt to navigate to that now -- by visiting [http://localhost:3000/posts/new](http://localhost:3000/posts/new) -- Rails will give you a routing error:
|
||||
|
||||
!images/getting_started/routing_error_no_route_matches.png(A routing error, no route matches /posts/new)!
|
||||
|
||||
|
@ -270,7 +270,7 @@ get "posts/new"
|
|||
|
||||
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.
|
||||
|
||||
With the route defined, requests can now be made to `/posts/new` in the application. Navigate to "http://localhost:3000/posts/new":http://localhost:3000/posts/new and you'll see another routing error:
|
||||
With the route defined, requests can now be made to `/posts/new` in the application. Navigate to [http://localhost:3000/posts/new](http://localhost:3000/posts/new) and you'll see another routing error:
|
||||
|
||||
!images/getting_started/routing_error_no_controller.png(Another routing error, uninitialized constant PostsController)!
|
||||
|
||||
|
@ -289,7 +289,7 @@ end
|
|||
|
||||
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.
|
||||
|
||||
If you refresh "http://localhost:3000/posts/new":http://localhost:3000/posts/new now, you'll get a new error:
|
||||
If you refresh [http://localhost:3000/posts/new](http://localhost:3000/posts/new) now, you'll get a new error:
|
||||
|
||||
!images/getting_started/unknown_action_new_for_posts.png(Unknown action new for PostsController!)!
|
||||
|
||||
|
@ -302,7 +302,7 @@ def new
|
|||
end
|
||||
```
|
||||
|
||||
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:
|
||||
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:
|
||||
|
||||
!images/getting_started/template_is_missing_posts_new.png(Template is missing for posts/new)!
|
||||
|
||||
|
@ -330,7 +330,7 @@ Go ahead now and create a new file at `app/views/posts/new.html.erb` and write t
|
|||
<h1>New Post</h1>
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
### The first form
|
||||
|
||||
|
@ -580,7 +580,7 @@ content:
|
|||
```
|
||||
|
||||
Finally, if you now go to
|
||||
"http://localhost:3000/posts/new":http://localhost:3000/posts/new you'll
|
||||
[http://localhost:3000/posts/new](http://localhost:3000/posts/new) you'll
|
||||
be able to create a post. Try it!
|
||||
|
||||
!images/getting_started/show_action_for_posts.png(Show action for posts)!
|
||||
|
@ -706,7 +706,7 @@ end
|
|||
|
||||
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.
|
||||
Accessible attributes and the mass assignment problem is covered in details in the "Security guide":security.html#mass-assignment
|
||||
Accessible attributes and the mass assignment problem is covered in details in the [Security guide](security.html#mass-assignment)
|
||||
|
||||
### Adding Some Validation
|
||||
|
||||
|
@ -758,7 +758,7 @@ Notice that inside the `create` action we use `render` instead of `redirect_to`
|
|||
returns `false`. The `render` method is used so that the `@post` object is passed back to the `new` template when it is rendered. This rendering is done within the same request as the form submission, whereas the `redirect_to` will tell the browser to issue another request.
|
||||
|
||||
If you reload
|
||||
"http://localhost:3000/posts/new":http://localhost:3000/posts/new and
|
||||
[http://localhost:3000/posts/new](http://localhost:3000/posts/new) and
|
||||
try to save a post without a title, Rails will send you back to the
|
||||
form, but that's not very useful. You need to tell the user that
|
||||
something went wrong. To do that, you'll modify
|
||||
|
@ -811,7 +811,7 @@ with class `field_with_errors`. You can define a css rule to make them
|
|||
standout.
|
||||
|
||||
Now you'll get a nice error message when saving a post without title when you
|
||||
attempt to do just that on the "new post form(http://localhost:3000/posts/new)":http://localhost:3000/posts/new.
|
||||
attempt to do just that on the [new post form(http://localhost:3000/posts/new)](http://localhost:3000/posts/new).
|
||||
|
||||
!images/getting_started/form_with_errors.png(Form With Errors)!
|
||||
|
||||
|
@ -1044,7 +1044,7 @@ Then do the same for the `app/views/posts/edit.html.erb` view:
|
|||
<%= link_to 'Back', :action => :index %>
|
||||
```
|
||||
|
||||
Point your browser to "http://localhost:3000/posts/new":http://localhost:3000/posts/new and
|
||||
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
|
||||
post and you'll receive the following error:
|
||||
|
||||
|
@ -1223,7 +1223,7 @@ posts the app still works as before.
|
|||
TIP: In general, Rails encourages the use of resources objects in place
|
||||
of declaring routes manually. It was only done in this guide as a learning
|
||||
exercise. For more information about routing, see
|
||||
"Rails Routing from the Outside In":routing.html.
|
||||
[Rails Routing from the Outside In](routing.html).
|
||||
|
||||
Adding a Second Model
|
||||
---------------------
|
||||
|
@ -1738,10 +1738,10 @@ update it and experiment on your own. But you don't have to do everything
|
|||
without help. As you need assistance getting up and running with Rails, feel
|
||||
free to consult these support resources:
|
||||
|
||||
* The "Ruby on Rails guides":index.html
|
||||
* The "Ruby on Rails Tutorial":http://railstutorial.org/book
|
||||
* The "Ruby on Rails mailing list":http://groups.google.com/group/rubyonrails-talk
|
||||
* The "#rubyonrails":irc://irc.freenode.net/#rubyonrails channel on irc.freenode.net
|
||||
* The [Ruby on Rails guides](index.html)
|
||||
* The [Ruby on Rails Tutorial](http://railstutorial.org/book)
|
||||
* The [Ruby on Rails mailing list](http://groups.google.com/group/rubyonrails-talk)
|
||||
* The [#rubyonrails](irc://irc.freenode.net/#rubyonrails) channel on irc.freenode.net
|
||||
|
||||
Rails also comes with built-in help that you can generate using the rake command-line utility:
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ This guide will walk you through the I18n API and contains a tutorial on how to
|
|||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
NOTE: The Ruby I18n framework provides you with all necessary means for internationalization/localization of your Rails application. You may, however, use any of various plugins and extensions available, which add additional functionality or features. See the Rails "I18n Wiki":http://rails-i18n.org/wiki for more information.
|
||||
NOTE: The Ruby I18n framework provides you with all necessary means for internationalization/localization of your Rails application. You may, however, use any of various plugins and extensions available, which add additional functionality or features. See the Rails [I18n Wiki](http://rails-i18n.org/wiki) for more information.
|
||||
|
||||
How I18n in Ruby on Rails Works
|
||||
-------------------------------
|
||||
|
@ -42,7 +42,7 @@ Thus, the Ruby I18n gem is split into two parts:
|
|||
|
||||
As a user you should always only access the public methods on the I18n module, but it is useful to know about the capabilities of the backend.
|
||||
|
||||
NOTE: It is possible (or even desirable) to swap the shipped Simple backend with a more powerful one, which would store translation data in a relational database, GetText dictionary, or similar. See section "Using different backends":#using-different-backends below.
|
||||
NOTE: It is possible (or even desirable) to swap the shipped Simple backend with a more powerful one, which would store translation data in a relational database, GetText dictionary, or similar. See section [Using different backends](#using-different-backends) below.
|
||||
|
||||
### The Public I18n API
|
||||
|
||||
|
@ -90,11 +90,11 @@ en:
|
|||
hello: "Hello world"
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
The I18n library will use *English* as a *default locale*, i.e. if you don't set a different locale, `:en` will be used for looking up translations.
|
||||
|
||||
NOTE: The i18n library takes a *pragmatic approach* to locale keys (after "some discussion":http://groups.google.com/group/rails-i18n/browse_thread/thread/14dede2c7dbe9470/80eec34395f64f3c?hl=en), including only the _locale_ ("language") part, like `:en`, `:pl`, not the _region_ part, like `:en-US` or `:en-GB`, which are traditionally used for separating "languages" and "regional setting" or "dialects". Many international applications use only the "language" element of a locale such as `:cs`, `:th` or `:es` (for Czech, Thai and Spanish). However, there are also regional differences within different language groups that may be important. For instance, in the `:en-US` locale you would have $ as a currency symbol, while in `:en-GB`, you would have £. Nothing stops you from separating regional and other settings in this way: you just have to provide full "English - United Kingdom" locale in a `:en-GB` dictionary. Various "Rails I18n plugins":http://rails-i18n.org/wiki such as "Globalize2":ht
|
||||
NOTE: The i18n library takes a *pragmatic approach* to locale keys (after [some discussion](http://groups.google.com/group/rails-i18n/browse_thread/thread/14dede2c7dbe9470/80eec34395f64f3c?hl=en), including only the _locale_ ("language") part, like `:en`, `:pl`, not the _region_ part, like `:en-US` or `:en-GB`, which are traditionally used for separating "languages" and "regional setting" or "dialects". Many international applications use only the "language" element of a locale such as `:cs`, `:th` or `:es` (for Czech, Thai and Spanish). However, there are also regional differences within different language groups that may be important. For instance, in the `:en-US` locale you would have $ as a currency symbol, while in `:en-GB`, you would have £. Nothing stops you from separating regional and other settings in this way: you just have to provide full "English - United Kingdom" locale in a `:en-GB` dictionary. Various [Rails I18n plugins](http://rails-i18n.org/wiki) such as [Globalize2](ht)
|
||||
|
||||
The *translations load path* (`I18n.load_path`) is just a Ruby Array of paths to your translation files that will be loaded automatically and available in your application. You can pick whatever directory and translation file naming scheme makes sense for you.
|
||||
|
||||
|
@ -130,7 +130,7 @@ If you want to translate your Rails application to a *single language other than
|
|||
|
||||
However, you would probably like to *provide support for more locales* in your application. In such case, you need to set and pass the locale between requests.
|
||||
|
||||
WARNING: You may be tempted to store the chosen locale in a _session_ or a <em>cookie</em>, however *do not do this*. The locale should be transparent and a part of the URL. This way you won't break people's basic assumptions about the web itself: if you send a URL to a friend, they should see the same page and content as you. A fancy word for this would be that you're being "<em>RESTful</em>":http://en.wikipedia.org/wiki/Representational_State_Transfer. Read more about the RESTful approach in "Stefan Tilkov's articles":http://www.infoq.com/articles/rest-introduction. Sometimes there are exceptions to this rule and those are discussed below.
|
||||
WARNING: You may be tempted to store the chosen locale in a _session_ or a <em>cookie</em>, however *do not do this*. The locale should be transparent and a part of the URL. This way you won't break people's basic assumptions about the web itself: if you send a URL to a friend, they should see the same page and content as you. A fancy word for this would be that you're being [<em>RESTful</em>](http://en.wikipedia.org/wiki/Representational_State_Transfer. Read more about the RESTful approach in [Stefan Tilkov's articles](http://www.infoq.com/articles/rest-introduction). Sometimes there are exceptions to this rule and those are discussed below.
|
||||
|
||||
The _setting part_ is easy. You can set the locale in a `before_filter` in the `ApplicationController` like this:
|
||||
|
||||
|
@ -207,7 +207,7 @@ This approach has almost the same set of advantages as setting the locale from t
|
|||
|
||||
Getting the locale from `params` and setting it accordingly is not hard; including it in every URL and thus *passing it through the requests* is. To include an explicit option in every URL (e.g. `link_to( books_url(:locale => I18n.locale))`) would be tedious and probably impossible, of course.
|
||||
|
||||
Rails contains infrastructure for "centralizing dynamic decisions about the URLs" in its "`ApplicationController#default_url_options`":http://api.rubyonrails.org/classes/ActionController/Base.html#M000515, which is useful precisely in this scenario: it enables us to set "defaults" for "`url_for`":http://api.rubyonrails.org/classes/ActionController/Base.html#M000503 and helper methods dependent on it (by implementing/overriding this method).
|
||||
Rails contains infrastructure for [centralizing dynamic decisions about the URLs" in its "`ApplicationController#default_url_options`](http://api.rubyonrails.org/classes/ActionController/Base.html#M000515, which is useful precisely in this scenario: it enables us to set "defaults" for [`url_for`](http://api.rubyonrails.org/classes/ActionController/Base.html#M000503) and helper methods dependent on it (by implementing/overriding this method).
|
||||
|
||||
We can include something like this in our `ApplicationController` then:
|
||||
|
||||
|
@ -223,7 +223,7 @@ Every helper method dependent on `url_for` (e.g. helpers for named routes like `
|
|||
|
||||
You may be satisfied with this. It does impact the readability of URLs, though, when the locale "hangs" at the end of every URL in your application. Moreover, from the architectural standpoint, locale is usually hierarchically above the other parts of the application domain: and URLs should reflect this.
|
||||
|
||||
You probably want URLs to look like this: `www.example.com/en/books` (which loads the English locale) and `www.example.com/nl/books` (which loads the Dutch locale). This is achievable with the "over-riding `default_url_options`" strategy from above: you just have to set up your routes with "`scoping`":http://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Scoping.html option in this way:
|
||||
You probably want URLs to look like this: `www.example.com/en/books` (which loads the English locale) and `www.example.com/nl/books` (which loads the Dutch locale). This is achievable with the [over-riding `default_url_options`" strategy from above: you just have to set up your routes with "`scoping`](http://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Scoping.html) option in this way:
|
||||
|
||||
```ruby
|
||||
# config/routes.rb
|
||||
|
@ -256,7 +256,7 @@ match '/:locale' => 'dashboard#index'
|
|||
|
||||
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.)
|
||||
|
||||
NOTE: Have a look at two plugins which simplify work with routes in this way: Sven Fuchs's "routing_filter":https://github.com/svenfuchs/routing-filter/tree/master and Raul Murciano's "translate_routes":https://github.com/raul/translate_routes/tree/master.
|
||||
NOTE: Have a look at two plugins which simplify work with routes in this way: Sven Fuchs's [routing_filter](https://github.com/svenfuchs/routing-filter/tree/master and Raul Murciano's [translate_routes](https://github.com/raul/translate_routes/tree/master).
|
||||
|
||||
### Setting the Locale from the Client Supplied Information
|
||||
|
||||
|
@ -265,7 +265,7 @@ In specific cases, it would make sense to set the locale from client-supplied in
|
|||
|
||||
#### Using `Accept-Language`
|
||||
|
||||
One source of client supplied information would be an `Accept-Language` HTTP header. People may "set this in their browser":http://www.w3.org/International/questions/qa-lang-priorities or other clients (such as _curl_).
|
||||
One source of client supplied information would be an `Accept-Language` HTTP header. People may [set this in their browser](http://www.w3.org/International/questions/qa-lang-priorities) or other clients (such as _curl_).
|
||||
|
||||
A trivial implementation of using an `Accept-Language` header would be:
|
||||
|
||||
|
@ -281,11 +281,11 @@ def extract_locale_from_accept_language_header
|
|||
end
|
||||
```
|
||||
|
||||
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.
|
||||
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).
|
||||
|
||||
#### Using GeoIP (or Similar) Database
|
||||
|
||||
Another way of choosing the locale from client information would be to use a database for mapping the client IP to the region, such as "GeoIP Lite Country":http://www.maxmind.com/app/geolitecountry. The mechanics of the code would be very similar to the code above -- you would need to query the database for the user's IP, and look up your preferred locale for the country/region/city returned.
|
||||
Another way of choosing the locale from client information would be to use a database for mapping the client IP to the region, such as [GeoIP Lite Country](http://www.maxmind.com/app/geolitecountry). The mechanics of the code would be very similar to the code above -- you would need to query the database for the user's IP, and look up your preferred locale for the country/region/city returned.
|
||||
|
||||
#### User Profile
|
||||
|
||||
|
@ -407,7 +407,7 @@ So that would give you:
|
|||
|
||||
!images/i18n/demo_localized_pirate.png(rails i18n demo localized time to pirate)!
|
||||
|
||||
TIP: Right now you might need to add some more date/time formats in order to make the I18n backend work as expected (at least for the 'pirate' locale). Of course, there's a great chance that somebody already did all the work by *translating Rails' defaults for your locale*. See the "rails-i18n repository at Github":https://github.com/svenfuchs/rails-i18n/tree/master/rails/locale for an archive of various locale files. When you put such file(s) in `config/locales/` directory, they will automatically be ready for use.
|
||||
TIP: Right now you might need to add some more date/time formats in order to make the I18n backend work as expected (at least for the 'pirate' locale). Of course, there's a great chance that somebody already did all the work by *translating Rails' defaults for your locale*. See the [rails-i18n repository at Github](https://github.com/svenfuchs/rails-i18n/tree/master/rails/locale) for an archive of various locale files. When you put such file(s) in `config/locales/` directory, they will automatically be ready for use.
|
||||
|
||||
### Inflection Rules For Other Locales
|
||||
|
||||
|
@ -458,7 +458,7 @@ NOTE: The default locale loading mechanism in Rails does not load locale files i
|
|||
|
||||
```
|
||||
|
||||
Do check the "Rails i18n Wiki":http://rails-i18n.org/wiki for list of tools available for managing translations.
|
||||
Do check the [Rails i18n Wiki](http://rails-i18n.org/wiki) for list of tools available for managing translations.
|
||||
|
||||
Overview of the I18n API Features
|
||||
---------------------------------
|
||||
|
@ -574,7 +574,7 @@ If a translation uses `:default` or `:scope` as an interpolation variable, an `I
|
|||
|
||||
### Pluralization
|
||||
|
||||
In English there are only one singular and one plural form for a given string, e.g. "1 message" and "2 messages". Other languages ("Arabic":http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html#ar, "Japanese":http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html#ja, "Russian":http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html#ru and many more) have different grammars that have additional or fewer "plural forms":http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html. Thus, the I18n API provides a flexible pluralization feature.
|
||||
In English there are only one singular and one plural form for a given string, e.g. "1 message" and "2 messages". Other languages ([Arabic](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html#ar), [Japanese](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html#ja), [Russian](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html#ru) and many more) have different grammars that have additional or fewer [plural forms](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html). Thus, the I18n API provides a flexible pluralization feature.
|
||||
|
||||
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:
|
||||
|
||||
|
@ -826,23 +826,23 @@ Rails uses fixed strings and other localizations, such as format strings and oth
|
|||
|
||||
#### Action View Helper Methods
|
||||
|
||||
* `distance_of_time_in_words` translates and pluralizes its result and interpolates the number of seconds, minutes, hours, and so on. See "datetime.distance_in_words":https://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L51 translations.
|
||||
* `distance_of_time_in_words` translates and pluralizes its result and interpolates the number of seconds, minutes, hours, and so on. See [datetime.distance_in_words](https://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L51) translations.
|
||||
|
||||
* `datetime_select` and `select_month` use translated month names for populating the resulting select tag. See "date.month_names":https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L15 for translations. `datetime_select` also looks up the order option from "date.order":https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L18 (unless you pass the option explicitly). All date selection helpers translate the prompt using the translations in the "datetime.prompts":https://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L83 scope if applicable.
|
||||
* `datetime_select` and `select_month` use translated month names for populating the resulting select tag. See [date.month_names](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L15) for translations. `datetime_select` also looks up the order option from [date.order](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L18) (unless you pass the option explicitly). All date selection helpers translate the prompt using the translations in the [datetime.prompts](https://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L83) scope if applicable.
|
||||
|
||||
* The `number_to_currency`, `number_with_precision`, `number_to_percentage`, `number_with_delimiter`, and `number_to_human_size` helpers use the number format settings located in the "number":https://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L2 scope.
|
||||
* The `number_to_currency`, `number_with_precision`, `number_to_percentage`, `number_with_delimiter`, and `number_to_human_size` helpers use the number format settings located in the [number](https://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L2) scope.
|
||||
|
||||
#### Active Model Methods
|
||||
|
||||
* `model_name.human` and `human_attribute_name` use translations for model names and attribute names if available in the "activerecord.models":https://github.com/rails/rails/blob/master/activerecord/lib/active_record/locale/en.yml#L29 scope. They also support translations for inherited class names (e.g. for use with STI) as explained above in "Error message scopes".
|
||||
* `model_name.human` and `human_attribute_name` use translations for model names and attribute names if available in the [activerecord.models](https://github.com/rails/rails/blob/master/activerecord/lib/active_record/locale/en.yml#L29) scope. They also support translations for inherited class names (e.g. for use with STI) as explained above in "Error message scopes".
|
||||
|
||||
* `ActiveModel::Errors#generate_message` (which is used by Active Model validations but may also be used manually) uses `model_name.human` and `human_attribute_name` (see above). It also translates the error message and supports translations for inherited class names as explained above in "Error message scopes".
|
||||
|
||||
* `ActiveModel::Errors#full_messages` prepends the attribute name to the error message using a separator that will be looked up from "errors.format":https://github.com/rails/rails/blob/master/activemodel/lib/active_model/locale/en.yml#L4 (and which defaults to `"%{attribute} %{message}"`).
|
||||
* `ActiveModel::Errors#full_messages` prepends the attribute name to the error message using a separator that will be looked up from [errors.format](https://github.com/rails/rails/blob/master/activemodel/lib/active_model/locale/en.yml#L4) (and which defaults to `"%{attribute} %{message}"`).
|
||||
|
||||
#### Active Support Methods
|
||||
|
||||
* `Array#to_sentence` uses format settings as given in the "support.array":https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L30 scope.
|
||||
* `Array#to_sentence` uses format settings as given in the [support.array](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L30) scope.
|
||||
|
||||
Customize your I18n Setup
|
||||
-------------------------
|
||||
|
@ -923,7 +923,7 @@ Conclusion
|
|||
|
||||
At this point you should have a good overview about how I18n support in Ruby on Rails works and are ready to start translating your project.
|
||||
|
||||
If you find anything missing or wrong in this guide, please file a ticket on our "issue tracker":http://i18n.lighthouseapp.com/projects/14948-rails-i18n/overview. If you want to discuss certain portions or have questions, please sign up to our "mailing list":http://groups.google.com/group/rails-i18n.
|
||||
If you find anything missing or wrong in this guide, please file a ticket on our [issue tracker](http://i18n.lighthouseapp.com/projects/14948-rails-i18n/overview). If you want to discuss certain portions or have questions, please sign up to our [mailing list](http://groups.google.com/group/rails-i18n).
|
||||
|
||||
|
||||
Contributing to Rails I18n
|
||||
|
@ -931,35 +931,35 @@ Contributing to Rails I18n
|
|||
|
||||
I18n support in Ruby on Rails was introduced in the release 2.2 and is still evolving. The project follows the good Ruby on Rails development tradition of evolving solutions in plugins and real applications first, and only then cherry-picking the best-of-breed of most widely useful features for inclusion in the core.
|
||||
|
||||
Thus we encourage everybody to experiment with new ideas and features in plugins or other libraries and make them available to the community. (Don't forget to announce your work on our "mailing list":http://groups.google.com/group/rails-i18n!)
|
||||
Thus we encourage everybody to experiment with new ideas and features in plugins or other libraries and make them available to the community. (Don't forget to announce your work on our [mailing list](http://groups.google.com/group/rails-i18n!))
|
||||
|
||||
If you find your own locale (language) missing from our "example translations data":https://github.com/svenfuchs/rails-i18n/tree/master/rails/locale repository for Ruby on Rails, please "_fork_":https://github.com/guides/fork-a-project-and-submit-your-modifications the repository, add your data and send a "pull request":https://github.com/guides/pull-requests.
|
||||
If you find your own locale (language) missing from our [example translations data](https://github.com/svenfuchs/rails-i18n/tree/master/rails/locale) repository for Ruby on Rails, please [_fork_](https://github.com/guides/fork-a-project-and-submit-your-modifications) the repository, add your data and send a [pull request](https://github.com/guides/pull-requests).
|
||||
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
* "rails-i18n.org":http://rails-i18n.org - Homepage of the rails-i18n project. You can find lots of useful resources on the "wiki":http://rails-i18n.org/wiki.
|
||||
* "Google group: rails-i18n":http://groups.google.com/group/rails-i18n - The project's mailing list.
|
||||
* "Github: rails-i18n":https://github.com/svenfuchs/rails-i18n/tree/master - Code repository for the rails-i18n project. Most importantly you can find lots of "example translations":https://github.com/svenfuchs/rails-i18n/tree/master/rails/locale for Rails that should work for your application in most cases.
|
||||
* "Github: i18n":https://github.com/svenfuchs/i18n/tree/master - Code repository for the i18n gem.
|
||||
* "Lighthouse: rails-i18n":http://i18n.lighthouseapp.com/projects/14948-rails-i18n/overview - Issue tracker for the rails-i18n project.
|
||||
* "Lighthouse: i18n":http://i18n.lighthouseapp.com/projects/14947-ruby-i18n/overview - Issue tracker for the i18n gem.
|
||||
* [rails-i18n.org](http://rails-i18n.org) - Homepage of the rails-i18n project. You can find lots of useful resources on the [wiki](http://rails-i18n.org/wiki).
|
||||
* [Google group: rails-i18n](http://groups.google.com/group/rails-i18n) - The project's mailing list.
|
||||
* [Github: rails-i18n](https://github.com/svenfuchs/rails-i18n/tree/master) - Code repository for the rails-i18n project. Most importantly you can find lots of [example translations](https://github.com/svenfuchs/rails-i18n/tree/master/rails/locale) for Rails that should work for your application in most cases.
|
||||
* [Github: i18n](https://github.com/svenfuchs/i18n/tree/master) - Code repository for the i18n gem.
|
||||
* [Lighthouse: rails-i18n](http://i18n.lighthouseapp.com/projects/14948-rails-i18n/overview) - Issue tracker for the rails-i18n project.
|
||||
* [Lighthouse: i18n](http://i18n.lighthouseapp.com/projects/14947-ruby-i18n/overview) - Issue tracker for the i18n gem.
|
||||
|
||||
|
||||
Authors
|
||||
-------
|
||||
|
||||
* "Sven Fuchs":http://www.workingwithrails.com/person/9963-sven-fuchs (initial author)
|
||||
* "Karel Minařík":http://www.workingwithrails.com/person/7476-karel-mina-k
|
||||
* [Sven Fuchs](http://www.workingwithrails.com/person/9963-sven-fuchs) (initial author)
|
||||
* [Karel Minařík](http://www.workingwithrails.com/person/7476-karel-mina-k)
|
||||
|
||||
If you found this guide useful, please consider recommending its authors on "workingwithrails":http://www.workingwithrails.com.
|
||||
If you found this guide useful, please consider recommending its authors on [workingwithrails](http://www.workingwithrails.com).
|
||||
|
||||
|
||||
Footnotes
|
||||
---------
|
||||
|
||||
fn1. Or, to quote "Wikipedia":http://en.wikipedia.org/wiki/Internationalization_and_localization: _"Internationalization is the process of designing a software application so that it can be adapted to various languages and regions without engineering changes. Localization is the process of adapting software for a specific region or language by adding locale-specific components and translating text."_
|
||||
fn1. Or, to quote [Wikipedia](http://en.wikipedia.org/wiki/Internationalization_and_localization:) _"Internationalization is the process of designing a software application so that it can be adapted to various languages and regions without engineering changes. Localization is the process of adapting software for a specific region or language by adding locale-specific components and translating text."_
|
||||
|
||||
fn2. Other backends might allow or require to use other formats, e.g. a GetText backend might allow to read GetText files.
|
||||
|
||||
|
|
|
@ -675,9 +675,9 @@ There are three tag options available for the `auto_discovery_link_tag`:
|
|||
|
||||
The `javascript_include_tag` helper returns an HTML `script` tag for each source provided.
|
||||
|
||||
If you are using Rails with the "Asset Pipeline":asset_pipeline.html enabled, this helper will generate a link to `/assets/javascripts/` rather than `public/javascripts` which was used in earlier versions of Rails. This link is then served by the Sprockets gem, which was introduced in Rails 3.1.
|
||||
If you are using Rails with the [Asset Pipeline](asset_pipeline.html) enabled, this helper will generate a link to `/assets/javascripts/` rather than `public/javascripts` which was used in earlier versions of Rails. This link is then served by the Sprockets gem, which was introduced in Rails 3.1.
|
||||
|
||||
A JavaScript file within a Rails application or Rails engine goes in one of three locations: `app/assets`, `lib/assets` or `vendor/assets`. These locations are explained in detail in the "Asset Organization section in the Asset Pipeline Guide":asset_pipeline.html#asset-organization
|
||||
A JavaScript file within a Rails application or Rails engine goes in one of three locations: `app/assets`, `lib/assets` or `vendor/assets`. These locations are explained in detail in the [Asset Organization section in the Asset Pipeline Guide](asset_pipeline.html#asset-organization)
|
||||
|
||||
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:
|
||||
|
||||
|
@ -724,7 +724,7 @@ Outputting `script` tags such as this:
|
|||
<script src="/javascripts/jquery_ujs.js"></script>
|
||||
```
|
||||
|
||||
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
|
||||
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)
|
||||
|
||||
WARNING: If you are using the asset pipeline, this tag will render a `script` tag for an asset called `defaults.js`, which would not exist in your application unless you've explicitly created it.
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ class AddReceiveNewsletterToUsers < ActiveRecord::Migration
|
|||
end
|
||||
```
|
||||
|
||||
NOTE: Some "caveats":#using-models-in-your-migrations apply to using models in
|
||||
NOTE: Some [caveats](#using-models-in-your-migrations) apply to using models in
|
||||
your migrations.
|
||||
|
||||
This migration adds a `receive_newsletter` column to the `users` table. We want
|
||||
|
@ -126,7 +126,7 @@ database independent way (you'll read about them in detail later):
|
|||
* `remove_reference`
|
||||
|
||||
If you need to perform tasks specific to your database (e.g., create a
|
||||
"foreign key":#active-record-and-referential-integrity constraint) then the
|
||||
[foreign key](#active-record-and-referential-integrity) constraint) then the
|
||||
`execute` method allows you to execute arbitrary SQL. A migration is just a
|
||||
regular Ruby class so you're not limited to these functions. For example, after
|
||||
adding a column you could write code to set the value of that column for
|
||||
|
@ -546,12 +546,12 @@ method to execute arbitrary SQL.
|
|||
|
||||
For more details and examples of individual methods, check the API documentation.
|
||||
In particular the documentation for
|
||||
"`ActiveRecord::ConnectionAdapters::SchemaStatements`":http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html
|
||||
[`ActiveRecord::ConnectionAdapters::SchemaStatements`](http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html)
|
||||
(which provides the methods available in the `up` and `down` methods),
|
||||
"`ActiveRecord::ConnectionAdapters::TableDefinition`":http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html
|
||||
[`ActiveRecord::ConnectionAdapters::TableDefinition`](http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html)
|
||||
(which provides the methods available on the object yielded by `create_table`)
|
||||
and
|
||||
"`ActiveRecord::ConnectionAdapters::Table`":http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html
|
||||
[`ActiveRecord::ConnectionAdapters::Table`](http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html)
|
||||
(which provides the methods available on the object yielded by `change_table`).
|
||||
|
||||
### Using the `change` Method
|
||||
|
@ -683,7 +683,7 @@ The `rake db:reset` task will drop the database, recreate it and load the
|
|||
current schema into it.
|
||||
|
||||
NOTE: This is not the same as running all the migrations - see the section on
|
||||
"schema.rb":#schema-dumping-and-you.
|
||||
[schema.rb](#schema-dumping-and-you).
|
||||
|
||||
### Running Specific Migrations
|
||||
|
||||
|
@ -905,7 +905,7 @@ Schema files are also useful if you want a quick look at what attributes an
|
|||
Active Record object has. This information is not in the model's code and is
|
||||
frequently spread across several migrations, but the information is nicely
|
||||
summed up in the schema file. The
|
||||
"annotate_models":https://github.com/ctran/annotate_models gem automatically
|
||||
[annotate_models](https://github.com/ctran/annotate_models) gem automatically
|
||||
adds and updates comments at the top of each model summarizing the schema if
|
||||
you desire that functionality.
|
||||
|
||||
|
@ -980,6 +980,6 @@ constraints in the database.
|
|||
|
||||
Although Active Record does not provide any tools for working directly with such
|
||||
features, the `execute` method can be used to execute arbitrary SQL. You could
|
||||
also use some plugin like "foreigner":https://github.com/matthuhiggins/foreigner
|
||||
also use some plugin like [foreigner](https://github.com/matthuhiggins/foreigner)
|
||||
which add foreign key support to Active Record (including support for dumping
|
||||
foreign keys in `db/schema.rb`).
|
||||
|
|
|
@ -9,7 +9,7 @@ In this guide you will:
|
|||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
NOTE: This guide assumes the user knows how to use the "Rails form helpers":form_helpers.html in general. Also, it’s *not* an API reference. For a complete reference please visit "the Rails API documentation":http://api.rubyonrails.org/.
|
||||
NOTE: This guide assumes the user knows how to use the [Rails form helpers](form_helpers.html) in general. Also, it’s *not* an API reference. For a complete reference please visit [the Rails API documentation](http://api.rubyonrails.org/).
|
||||
|
||||
|
||||
Model setup
|
||||
|
|
|
@ -144,7 +144,7 @@ end
|
|||
```
|
||||
|
||||
You can find more details about the `get` and `post` methods in the
|
||||
"Testing Rails Applications":testing.html guide.
|
||||
[Testing Rails Applications](testing.html) guide.
|
||||
|
||||
#### Model Example
|
||||
|
||||
|
@ -340,16 +340,16 @@ BrowsingTest#test_homepage (58 ms warmup)
|
|||
##### Flat
|
||||
|
||||
Flat output shows the metric—time, memory, etc—measure in each method.
|
||||
"Check Ruby-Prof documentation for a better explanation":http://ruby-prof.rubyforge.org/files/examples/flat_txt.html.
|
||||
[Check Ruby-Prof documentation for a better explanation](http://ruby-prof.rubyforge.org/files/examples/flat_txt.html).
|
||||
|
||||
##### Graph
|
||||
|
||||
Graph output shows the metric measure in each method, which methods call it and
|
||||
which methods it calls. "Check Ruby-Prof documentation for a better explanation":http://ruby-prof.rubyforge.org/files/examples/graph_txt.html.
|
||||
which methods it calls. [Check Ruby-Prof documentation for a better explanation](http://ruby-prof.rubyforge.org/files/examples/graph_txt.html).
|
||||
|
||||
##### Tree
|
||||
|
||||
Tree output is profiling information in calltree format for use by "kcachegrind":http://kcachegrind.sourceforge.net/html/Home.html
|
||||
Tree output is profiling information in calltree format for use by [kcachegrind](http://kcachegrind.sourceforge.net/html/Home.html)
|
||||
and similar tools.
|
||||
|
||||
##### Output Availability
|
||||
|
@ -398,7 +398,7 @@ Metrics and formats have different defaults depending on the interpreter in use.
|
|||
|Profiling |`[:wall_time]`|`[:flat, :graph]`|
|
||||
|
||||
As you've probably noticed by now, metrics and formats are specified using a
|
||||
symbol array with each name "underscored.":http://api.rubyonrails.org/classes/String.html#method-i-underscore
|
||||
symbol array with each name [underscored.](http://api.rubyonrails.org/classes/String.html#method-i-underscore)
|
||||
|
||||
### Performance Test Environment
|
||||
|
||||
|
@ -426,11 +426,11 @@ The recommended patches for each MRI version are:
|
|||
|1.8.7|ruby187gc|
|
||||
|1.9.2 and above|gcdata|
|
||||
|
||||
All of these can be found on "RVM's _patches_ directory":https://github.com/wayneeseguin/rvm/tree/master/patches/ruby
|
||||
All of these can be found on [RVM's _patches_ directory](https://github.com/wayneeseguin/rvm/tree/master/patches/ruby)
|
||||
under each specific interpreter version.
|
||||
|
||||
Concerning the installation itself, you can either do this easily by using
|
||||
"RVM":http://rvm.beginrescueend.com or you can build everything from source,
|
||||
[RVM](http://rvm.beginrescueend.com) or you can build everything from source,
|
||||
which is a little bit harder.
|
||||
|
||||
#### Install Using RVM
|
||||
|
@ -590,12 +590,12 @@ block and prints the result to the log file:
|
|||
Creating project (185.3ms)
|
||||
```
|
||||
|
||||
Please refer to the "API docs":http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html#method-i-benchmark
|
||||
Please refer to the [API docs](http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html#method-i-benchmark)
|
||||
for additional options to `benchmark()`.
|
||||
|
||||
### Controller
|
||||
|
||||
Similarly, you could use this helper method inside "controllers.":http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html
|
||||
Similarly, you could use this helper method inside [controllers.](http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html)
|
||||
|
||||
```ruby
|
||||
def process_projects
|
||||
|
@ -610,7 +610,7 @@ NOTE: `benchmark` is a class method inside controllers.
|
|||
|
||||
### View
|
||||
|
||||
And in "views":http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html:
|
||||
And in [views](http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html:)
|
||||
|
||||
```erb
|
||||
<% benchmark("Showing projects partial") do %>
|
||||
|
@ -643,7 +643,7 @@ Rails, out of which 2 ms were spent rendering views and none was spent
|
|||
communication with the database. It's safe to assume that the remaining 3 ms
|
||||
were spent inside the controller.
|
||||
|
||||
Michael Koziarski has an "interesting blog post":http://www.therailsway.com/2009/1/6/requests-per-second
|
||||
Michael Koziarski has an [interesting blog post](http://www.therailsway.com/2009/1/6/requests-per-second)
|
||||
explaining the importance of using milliseconds as the metric.
|
||||
|
||||
Useful Links
|
||||
|
@ -651,23 +651,23 @@ Useful Links
|
|||
|
||||
### Rails Plugins and Gems
|
||||
|
||||
* "Rails Analyzer":http://rails-analyzer.rubyforge.org
|
||||
* "Palmist":http://www.flyingmachinestudios.com/programming/announcing-palmist
|
||||
* "Rails Footnotes":https://github.com/josevalim/rails-footnotes/tree/master
|
||||
* "Query Reviewer":https://github.com/dsboulder/query_reviewer/tree/master
|
||||
* "MiniProfiler":http://www.miniprofiler.com
|
||||
* [Rails Analyzer](http://rails-analyzer.rubyforge.org)
|
||||
* [Palmist](http://www.flyingmachinestudios.com/programming/announcing-palmist)
|
||||
* [Rails Footnotes](https://github.com/josevalim/rails-footnotes/tree/master)
|
||||
* [Query Reviewer](https://github.com/dsboulder/query_reviewer/tree/master)
|
||||
* [MiniProfiler](http://www.miniprofiler.com)
|
||||
|
||||
### Generic Tools
|
||||
|
||||
* "httperf":http://www.hpl.hp.com/research/linux/httperf/
|
||||
* "ab":http://httpd.apache.org/docs/2.2/programs/ab.html
|
||||
* "JMeter":http://jakarta.apache.org/jmeter/
|
||||
* "kcachegrind":http://kcachegrind.sourceforge.net/html/Home.html
|
||||
* [httperf](http://www.hpl.hp.com/research/linux/httperf/)
|
||||
* [ab](http://httpd.apache.org/docs/2.2/programs/ab.html)
|
||||
* [JMeter](http://jakarta.apache.org/jmeter/)
|
||||
* [kcachegrind](http://kcachegrind.sourceforge.net/html/Home.html)
|
||||
|
||||
### Tutorials and Documentation
|
||||
|
||||
* "ruby-prof API Documentation":http://ruby-prof.rubyforge.org
|
||||
* "Request Profiling Railscast":http://railscasts.com/episodes/98-request-profiling - Outdated, but useful for understanding call graphs.
|
||||
* [ruby-prof API Documentation](http://ruby-prof.rubyforge.org)
|
||||
* [Request Profiling Railscast](http://railscasts.com/episodes/98-request-profiling) - Outdated, but useful for understanding call graphs.
|
||||
|
||||
Commercial Products
|
||||
-------------------
|
||||
|
@ -675,5 +675,5 @@ Commercial Products
|
|||
Rails has been lucky to have a few companies dedicated to Rails-specific
|
||||
performance tools. A couple of those are:
|
||||
|
||||
* "New Relic":http://www.newrelic.com
|
||||
* "Scout":http://scoutapp.com
|
||||
* [New Relic](http://www.newrelic.com)
|
||||
* [Scout](http://scoutapp.com)
|
||||
|
|
|
@ -83,7 +83,7 @@ Run `rake` to run the test. This test should fail because we haven't implemented
|
|||
```bash
|
||||
1) Error:
|
||||
test_to_squawk_prepends_the_word_squawk(CoreExtTest):
|
||||
NoMethodError: undefined method `to_squawk' for "Hello World":String
|
||||
NoMethodError: undefined method `to_squawk' for [Hello World](String)
|
||||
test/core_ext_test.rb:5:in `test_to_squawk_prepends_the_word_squawk'
|
||||
```
|
||||
|
||||
|
@ -393,7 +393,7 @@ Generators
|
|||
----------
|
||||
|
||||
Generators can be included in your gem simply by creating them in a lib/generators directory of your plugin. More information about
|
||||
the creation of generators can be found in the "Generators Guide":generators.html
|
||||
the creation of generators can be found in the [Generators Guide](generators.html)
|
||||
|
||||
Publishing your Gem
|
||||
-------------------
|
||||
|
@ -407,8 +407,8 @@ gem 'yaffle', :git => 'git://github.com/yaffle_watcher/yaffle.git'
|
|||
|
||||
After running `bundle install`, your gem functionality will be available to the application.
|
||||
|
||||
When the gem is ready to be shared as a formal release, it can be published to "RubyGems":http://www.rubygems.org.
|
||||
For more information about publishing gems to RubyGems, see: "Creating and Publishing Your First Ruby Gem":http://blog.thepete.net/2010/11/creating-and-publishing-your-first-ruby.html
|
||||
When the gem is ready to be shared as a formal release, it can be published to [RubyGems](http://www.rubygems.org).
|
||||
For more information about publishing gems to RubyGems, see: [Creating and Publishing Your First Ruby Gem](http://blog.thepete.net/2010/11/creating-and-publishing-your-first-ruby.html)
|
||||
|
||||
RDoc Documentation
|
||||
------------------
|
||||
|
@ -432,7 +432,7 @@ $ rake rdoc
|
|||
|
||||
### References
|
||||
|
||||
* "Developing a RubyGem using Bundler":https://github.com/radar/guides/blob/master/gem-development.md
|
||||
* "Using .gemspecs as Intended":http://yehudakatz.com/2010/04/02/using-gemspecs-as-intended/
|
||||
* "Gemspec Reference":http://docs.rubygems.org/read/chapter/20
|
||||
* "GemPlugins: A Brief Introduction to the Future of Rails Plugins":http://www.intridea.com/blog/2008/6/11/gemplugins-a-brief-introduction-to-the-future-of-rails-plugins
|
||||
* [Developing a RubyGem using Bundler](https://github.com/radar/guides/blob/master/gem-development.md)
|
||||
* [Using .gemspecs as Intended](http://yehudakatz.com/2010/04/02/using-gemspecs-as-intended/)
|
||||
* [Gemspec Reference](http://docs.rubygems.org/read/chapter/20)
|
||||
* [GemPlugins: A Brief Introduction to the Future of Rails Plugins](http://www.intridea.com/blog/2008/6/11/gemplugins-a-brief-introduction-to-the-future-of-rails-plugins)
|
||||
|
|
|
@ -17,9 +17,9 @@ Introduction to Rack
|
|||
|
||||
bq. Rack provides a minimal, modular and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the API for web servers, web frameworks, and software in between (the so-called middleware) into a single method call.
|
||||
|
||||
- "Rack API Documentation":http://rack.rubyforge.org/doc/
|
||||
- [Rack API Documentation](http://rack.rubyforge.org/doc/)
|
||||
|
||||
Explaining Rack is not really in the scope of this guide. In case you are not familiar with Rack's basics, you should check out the "Resources":#resources section below.
|
||||
Explaining Rack is not really in the scope of this guide. In case you are not familiar with Rack's basics, you should check out the [Resources](#resources) section below.
|
||||
|
||||
Rails on Rack
|
||||
-------------
|
||||
|
@ -138,7 +138,7 @@ use ActionDispatch::BestStandardsSupport
|
|||
run ApplicationName::Application.routes
|
||||
```
|
||||
|
||||
Purpose of each of this middlewares is explained in the "Internal Middlewares":#internal-middleware-stack section.
|
||||
Purpose of each of this middlewares is explained in the [Internal Middlewares](#internal-middleware-stack) section.
|
||||
|
||||
### Configuring Middleware Stack
|
||||
|
||||
|
@ -313,11 +313,11 @@ Resources
|
|||
|
||||
### Learning Rack
|
||||
|
||||
* "Official Rack Website":http://rack.github.com
|
||||
* "Introducing Rack":http://chneukirchen.org/blog/archive/2007/02/introducing-rack.html
|
||||
* "Ruby on Rack #1 - Hello Rack!":http://m.onkey.org/ruby-on-rack-1-hello-rack
|
||||
* "Ruby on Rack #2 - The Builder":http://m.onkey.org/ruby-on-rack-2-the-builder
|
||||
* [Official Rack Website](http://rack.github.com)
|
||||
* [Introducing Rack](http://chneukirchen.org/blog/archive/2007/02/introducing-rack.html)
|
||||
* [Ruby on Rack #1 - Hello Rack!](http://m.onkey.org/ruby-on-rack-1-hello-rack)
|
||||
* [Ruby on Rack #2 - The Builder](http://m.onkey.org/ruby-on-rack-2-the-builder)
|
||||
|
||||
### Understanding Middlewares
|
||||
|
||||
* "Railscast on Rack Middlewares":http://railscasts.com/episodes/151-rack-middleware
|
||||
* [Railscast on Rack Middlewares](http://railscasts.com/episodes/151-rack-middleware)
|
||||
|
|
|
@ -272,7 +272,7 @@ Deeply-nested resources quickly become cumbersome. In this case, for example, th
|
|||
/publishers/1/magazines/2/photos/3
|
||||
```
|
||||
|
||||
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:
|
||||
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:
|
||||
|
||||
TIP: _Resources should never be nested more than 1 level deep._
|
||||
|
||||
|
@ -921,7 +921,7 @@ TIP: You'll find that the output from `rake routes` is much more readable if you
|
|||
|
||||
### Testing Routes
|
||||
|
||||
Routes should be included in your testing strategy (just like the rest of your application). Rails offers three "built-in assertions":http://api.rubyonrails.org/classes/ActionDispatch/Assertions/RoutingAssertions.html designed to make testing routes simpler:
|
||||
Routes should be included in your testing strategy (just like the rest of your application). Rails offers three [built-in assertions](http://api.rubyonrails.org/classes/ActionDispatch/Assertions/RoutingAssertions.html) designed to make testing routes simpler:
|
||||
|
||||
* `assert_generates`
|
||||
* `assert_recognizes`
|
||||
|
|
|
@ -8,12 +8,12 @@ This guide documents guidelines for writing Ruby on Rails Guides. This guide fol
|
|||
Textile
|
||||
-------
|
||||
|
||||
Guides are written in "Textile":http://www.textism.com/tools/textile/. There is comprehensive "documentation":http://redcloth.org/hobix.com/textile/ and a "cheatsheet":http://redcloth.org/hobix.com/textile/quick.html for markup.
|
||||
Guides are written in [Textile](http://www.textism.com/tools/textile/). There is comprehensive [documentation](http://redcloth.org/hobix.com/textile/) and a [cheatsheet](http://redcloth.org/hobix.com/textile/quick.html) for markup.
|
||||
|
||||
Prologue
|
||||
--------
|
||||
|
||||
Each guide should start with motivational text at the top (that's the little introduction in the blue area). The prologue should tell the reader what the guide is about, and what they will learn. See for example the "Routing Guide":routing.html.
|
||||
Each guide should start with motivational text at the top (that's the little introduction in the blue area). The prologue should tell the reader what the guide is about, and what they will learn. See for example the [Routing Guide](routing.html).
|
||||
|
||||
Titles
|
||||
------
|
||||
|
@ -36,12 +36,12 @@ Use the same typography as in regular text:
|
|||
API Documentation Guidelines
|
||||
----------------------------
|
||||
|
||||
The guides and the API should be coherent and consistent where appropriate. Please have a look at these particular sections of the "API Documentation Guidelines":api_documentation_guidelines.html:
|
||||
The guides and the API should be coherent and consistent where appropriate. Please have a look at these particular sections of the [API Documentation Guidelines](api_documentation_guidelines.html:)
|
||||
|
||||
* "Wording":api_documentation_guidelines.html#wording
|
||||
* "Example Code":api_documentation_guidelines.html#example-code
|
||||
* "Filenames":api_documentation_guidelines.html#filenames
|
||||
* "Fonts":api_documentation_guidelines.html#fonts
|
||||
* [Wording](api_documentation_guidelines.html#wording)
|
||||
* [Example Code](api_documentation_guidelines.html#example-code)
|
||||
* [Filenames](api_documentation_guidelines.html#filenames)
|
||||
* [Fonts](api_documentation_guidelines.html#fonts)
|
||||
|
||||
Those guidelines apply also to guides.
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ config.force_ssl = true
|
|||
|
||||
* Instead of stealing a cookie unknown to the attacker, he fixes a user's session identifier (in the cookie) known to him. Read more about this so-called session fixation later.
|
||||
|
||||
The main objective of most attackers is to make money. The underground prices for stolen bank login accounts range from $10–$1000 (depending on the available amount of funds), $0.40–$20 for credit card numbers, $1–$8 for online auction site accounts and $4–$30 for email passwords, according to the "Symantec Global Internet Security Threat Report":http://eval.symantec.com/mktginfo/enterprise/white_papers/b-whitepaper_internet_security_threat_report_xiii_04-2008.en-us.pdf.
|
||||
The main objective of most attackers is to make money. The underground prices for stolen bank login accounts range from $10–$1000 (depending on the available amount of funds), $0.40–$20 for credit card numbers, $1–$8 for online auction site accounts and $4–$30 for email passwords, according to the [Symantec Global Internet Security Threat Report](http://eval.symantec.com/mktginfo/enterprise/white_papers/b-whitepaper_internet_security_threat_report_xiii_04-2008.en-us.pdf).
|
||||
|
||||
### Session Guidelines
|
||||
|
||||
|
@ -290,7 +290,7 @@ NOTE: _Make sure file uploads don't overwrite important files, and process media
|
|||
|
||||
Many web applications allow users to upload files. _(highlight)File names, which the user may choose (partly), should always be filtered_ as an attacker could use a malicious file name to overwrite any file on the server. If you store file uploads at /var/www/uploads, and the user enters a file name like “../../../etc/passwd”, it may overwrite an important file. Of course, the Ruby interpreter would need the appropriate permissions to do so – one more reason to run web servers, database servers and other programs as a less privileged Unix user.
|
||||
|
||||
When filtering user input file names, _(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:
|
||||
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
|
||||
def sanitize_filename(filename)
|
||||
|
@ -354,7 +354,7 @@ Refer to the Injection section for countermeasures against XSS. It is _(highligh
|
|||
|
||||
*CSRF* Cross-Site Reference Forgery (CSRF) is a gigantic attack method, it allows the attacker to do everything the administrator or Intranet user may do. As you have already seen above how CSRF works, here are a few examples of what attackers can do in the Intranet or admin interface.
|
||||
|
||||
A real-world example is a "router reconfiguration by CSRF":http://www.h-online.com/security/Symantec-reports-first-active-attack-on-a-DSL-router--/news/102352. The attackers sent a malicious e-mail, with CSRF in it, to Mexican users. The e-mail claimed there was an e-card waiting for them, but it also contained an image tag that resulted in a HTTP-GET request to reconfigure the user's router (which is a popular model in Mexico). The request changed the DNS-settings so that requests to a Mexico-based banking site would be mapped to the attacker's site. Everyone who accessed the banking site through that router saw the attacker's fake web site and had his credentials stolen.
|
||||
A real-world example is a [router reconfiguration by CSRF](http://www.h-online.com/security/Symantec-reports-first-active-attack-on-a-DSL-router--/news/102352). The attackers sent a malicious e-mail, with CSRF in it, to Mexican users. The e-mail claimed there was an e-card waiting for them, but it also contained an image tag that resulted in a HTTP-GET request to reconfigure the user's router (which is a popular model in Mexico). The request changed the DNS-settings so that requests to a Mexico-based banking site would be mapped to the attacker's site. Everyone who accessed the banking site through that router saw the attacker's fake web site and had his credentials stolen.
|
||||
|
||||
Another example changed Google Adsense's e-mail address and password by. If the victim was logged into Google Adsense, the administration interface for Google advertisements campaigns, an attacker could change his credentials.
|
||||
|
||||
|
@ -490,7 +490,7 @@ User Management
|
|||
|
||||
NOTE: _Almost every web application has to deal with authorization and authentication. Instead of rolling your own, it is advisable to use common plug-ins. But keep them up-to-date, too. A few additional precautions can make your application even more secure._
|
||||
|
||||
There are a number of authentication plug-ins for Rails available. Good ones, such as the popular "devise":https://github.com/plataformatec/devise and "authlogic":https://github.com/binarylogic/authlogic, store only encrypted passwords, not plain-text passwords. In Rails 3.1 you can use the built-in `has_secure_password` method which has similar features.
|
||||
There are a number of authentication plug-ins for Rails available. Good ones, such as the popular [devise](https://github.com/plataformatec/devise) and [authlogic](https://github.com/binarylogic/authlogic), store only encrypted passwords, not plain-text passwords. In Rails 3.1 you can use the built-in `has_secure_password` method which has similar features.
|
||||
|
||||
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):
|
||||
|
||||
|
@ -511,7 +511,7 @@ If the parameter was nil, the resulting SQL query will be
|
|||
SELECT * FROM users WHERE (users.activation_code IS NULL) LIMIT 1
|
||||
```
|
||||
|
||||
And thus it found the first user in the database, returned it and logged him in. You can find out more about it in "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.
|
||||
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.
|
||||
|
||||
### Brute-Forcing Accounts
|
||||
|
||||
|
@ -539,13 +539,13 @@ However, the attacker may also take over the account by changing the e-mail addr
|
|||
|
||||
#### Other
|
||||
|
||||
Depending on your web application, there may be more ways to hijack the user's account. In many cases CSRF and XSS will help to do so. For example, as in a CSRF vulnerability in "Google Mail":http://www.gnucitizen.org/blog/google-gmail-e-mail-hijack-technique/. In this proof-of-concept attack, the victim would have been lured to a web site controlled by the attacker. On that site is a crafted IMG-tag which results in a HTTP GET request that changes the filter settings of Google Mail. If the victim was logged in to Google Mail, the attacker would change the filters to forward all e-mails to his e-mail address. This is nearly as harmful as hijacking the entire account. As a countermeasure, _(highlight)review your application logic and eliminate all XSS and CSRF vulnerabilities_.
|
||||
Depending on your web application, there may be more ways to hijack the user's account. In many cases CSRF and XSS will help to do so. For example, as in a CSRF vulnerability in [Google Mail](http://www.gnucitizen.org/blog/google-gmail-e-mail-hijack-technique/). In this proof-of-concept attack, the victim would have been lured to a web site controlled by the attacker. On that site is a crafted IMG-tag which results in a HTTP GET request that changes the filter settings of Google Mail. If the victim was logged in to Google Mail, the attacker would change the filters to forward all e-mails to his e-mail address. This is nearly as harmful as hijacking the entire account. As a countermeasure, _(highlight)review your application logic and eliminate all XSS and CSRF vulnerabilities_.
|
||||
|
||||
### CAPTCHAs
|
||||
|
||||
INFO: _A CAPTCHA is a challenge-response test to determine that the response is not generated by a computer. It is often used to protect comment forms from automatic spam bots by asking the user to type the letters of a distorted image. The idea of a negative CAPTCHA is not for a user to prove that he is human, but reveal that a robot is a robot._
|
||||
|
||||
But not only spam robots (bots) are a problem, but also automatic login bots. A popular CAPTCHA API is "reCAPTCHA":http://recaptcha.net/ which displays two distorted images of words from old books. It also adds an angled line, rather than a distorted background and high levels of warping on the text as earlier CAPTCHAs did, because the latter were broken. As a bonus, using reCAPTCHA helps to digitize old books. "ReCAPTCHA":http://ambethia.com/recaptcha/ is also a Rails plug-in with the same name as the API.
|
||||
But not only spam robots (bots) are a problem, but also automatic login bots. A popular CAPTCHA API is [reCAPTCHA](http://recaptcha.net/) which displays two distorted images of words from old books. It also adds an angled line, rather than a distorted background and high levels of warping on the text as earlier CAPTCHAs did, because the latter were broken. As a bonus, using reCAPTCHA helps to digitize old books. [ReCAPTCHA](http://ambethia.com/recaptcha/) is also a Rails plug-in with the same name as the API.
|
||||
|
||||
You will get two keys from the API, a public and a private key, which you have to put into your Rails environment. After that you can use the recaptcha_tags method in the view, and the verify_recaptcha method in the controller. Verify_recaptcha will return false if the validation fails.
|
||||
The problem with CAPTCHAs is, they are annoying. Additionally, some visually impaired users have found certain kinds of distorted CAPTCHAs difficult to read. The idea of negative CAPTCHAs is not to ask a user to proof that he is human, but reveal that a spam robot is a bot.
|
||||
|
@ -560,7 +560,7 @@ Here are some ideas how to hide honeypot fields by JavaScript and/or CSS:
|
|||
|
||||
The most simple negative CAPTCHA is one hidden honeypot field. On the server side, you will check the value of the field: If it contains any text, it must be a bot. Then, you can either ignore the post or return a positive result, but not saving the post to the database. This way the bot will be satisfied and moves on. You can do this with annoying users, too.
|
||||
|
||||
You can find more sophisticated negative CAPTCHAs in Ned Batchelder's "blog post":http://nedbatchelder.com/text/stopbots.html:
|
||||
You can find more sophisticated negative CAPTCHAs in Ned Batchelder's [blog post](http://nedbatchelder.com/text/stopbots.html:)
|
||||
|
||||
* Include a field with the current UTC time-stamp in it and check it on the server. If it is too far in the past, or if it is in the future, the form is invalid.
|
||||
* Randomize the field names
|
||||
|
@ -582,7 +582,7 @@ config.filter_parameters << :password
|
|||
|
||||
INFO: _Do you find it hard to remember all your passwords? Don't write them down, but use the initial letters of each word in an easy to remember sentence._
|
||||
|
||||
Bruce Schneier, a security technologist, "has analyzed":http://www.schneier.com/blog/archives/2006/12/realworld_passw.html 34,000 real-world user names and passwords from the MySpace phishing attack mentioned <a href="#examples-from-the-underground">below</a>. It turns out that most of the passwords are quite easy to crack. The 20 most common passwords are:
|
||||
Bruce Schneier, a security technologist, [has analyzed](http://www.schneier.com/blog/archives/2006/12/realworld_passw.html) 34,000 real-world user names and passwords from the MySpace phishing attack mentioned <a href="#examples-from-the-underground">below</a>. It turns out that most of the passwords are quite easy to crack. The 20 most common passwords are:
|
||||
|
||||
password1, abc123, myspace1, password, blink182, qwerty1, ****you, 123abc, baseball1, football1, 123456, soccer, monkey1, liverpool1, princess1, jordan23, slipknot1, superman1, iloveyou1, and monkey.
|
||||
|
||||
|
@ -732,7 +732,7 @@ SELECT * FROM projects WHERE (name = '') UNION
|
|||
|
||||
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.
|
||||
|
||||
Also, the second query renames some columns with the AS statement so that the web application displays the values from the user table. Be sure to update your Rails "to at least 2.1.1":http://www.rorsecurity.info/2008/09/08/sql-injection-issue-in-limit-and-offset-parameter/.
|
||||
Also, the second query renames some columns with the AS statement so that the web application displays the values from the user table. Be sure to update your Rails [to at least 2.1.1](http://www.rorsecurity.info/2008/09/08/sql-injection-issue-in-limit-and-offset-parameter/).
|
||||
|
||||
#### Countermeasures
|
||||
|
||||
|
@ -760,13 +760,13 @@ INFO: _The most widespread, and one of the most devastating security vulnerabili
|
|||
|
||||
An entry point is a vulnerable URL and its parameters where an attacker can start an attack.
|
||||
|
||||
The most common entry points are message posts, user comments, and guest books, but project titles, document names and search result pages have also been vulnerable - just about everywhere where the user can input data. But the input does not necessarily have to come from input boxes on web sites, it can be in any URL parameter – obvious, hidden or internal. Remember that the user may intercept any traffic. Applications, such as the "Live HTTP Headers Firefox plugin":http://livehttpheaders.mozdev.org/, or client-site proxies make it easy to change requests.
|
||||
The most common entry points are message posts, user comments, and guest books, but project titles, document names and search result pages have also been vulnerable - just about everywhere where the user can input data. But the input does not necessarily have to come from input boxes on web sites, it can be in any URL parameter – obvious, hidden or internal. Remember that the user may intercept any traffic. Applications, such as the [Live HTTP Headers Firefox plugin](http://livehttpheaders.mozdev.org/), or client-site proxies make it easy to change requests.
|
||||
|
||||
XSS attacks work like this: An attacker injects some code, the web application saves it and displays it on a page, later presented to a victim. Most XSS examples simply display an alert box, but it is more powerful than that. XSS can steal the cookie, hijack the session, redirect the victim to a fake website, display advertisements for the benefit of the attacker, change elements on the web site to get confidential information or install malicious software through security holes in the web browser.
|
||||
|
||||
During the second half of 2007, there were 88 vulnerabilities reported in Mozilla browsers, 22 in Safari, 18 in IE, and 12 in Opera. The "Symantec Global Internet Security threat report":http://eval.symantec.com/mktginfo/enterprise/white_papers/b-whitepaper_internet_security_threat_report_xiii_04-2008.en-us.pdf also documented 239 browser plug-in vulnerabilities in the last six months of 2007. "Mpack":http://pandalabs.pandasecurity.com/mpack-uncovered/ is a very active and up-to-date attack framework which exploits these vulnerabilities. For criminal hackers, it is very attractive to exploit an SQL-Injection vulnerability in a web application framework and insert malicious code in every textual table column. In April 2008 more than 510,000 sites were hacked like this, among them the British government, United Nations, and many more high targets.
|
||||
During the second half of 2007, there were 88 vulnerabilities reported in Mozilla browsers, 22 in Safari, 18 in IE, and 12 in Opera. The [Symantec Global Internet Security threat report](http://eval.symantec.com/mktginfo/enterprise/white_papers/b-whitepaper_internet_security_threat_report_xiii_04-2008.en-us.pdf) also documented 239 browser plug-in vulnerabilities in the last six months of 2007. [Mpack](http://pandalabs.pandasecurity.com/mpack-uncovered/) is a very active and up-to-date attack framework which exploits these vulnerabilities. For criminal hackers, it is very attractive to exploit an SQL-Injection vulnerability in a web application framework and insert malicious code in every textual table column. In April 2008 more than 510,000 sites were hacked like this, among them the British government, United Nations, and many more high targets.
|
||||
|
||||
A relatively new, and unusual, form of entry points are banner advertisements. In earlier 2008, malicious code appeared in banner ads on popular sites, such as MySpace and Excite, according to "Trend Micro":http://blog.trendmicro.com/myspace-excite-and-blick-serve-up-malicious-banner-ads/.
|
||||
A relatively new, and unusual, form of entry points are banner advertisements. In earlier 2008, malicious code appeared in banner ads on popular sites, such as MySpace and Excite, according to [Trend Micro](http://blog.trendmicro.com/myspace-excite-and-blick-serve-up-malicious-banner-ads/).
|
||||
|
||||
#### HTML/JavaScript Injection
|
||||
|
||||
|
@ -805,7 +805,7 @@ The log files on www.attacker.com will read like this:
|
|||
GET http://www.attacker.com/_app_session=836c1c25278e5b321d6bea4f19cb57e2
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
##### Defacement
|
||||
|
||||
|
@ -815,7 +815,7 @@ With web page defacement an attacker can do a lot of things, for example, presen
|
|||
<iframe name=”StatPage” src="http://58.xx.xxx.xxx" width=5 height=5 style=”display:none”></iframe>
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
A more specialized attack could overlap the entire web site or display a login form, which looks the same as the site's original, but transmits the user name and password to the attacker's site. Or it could use CSS and/or JavaScript to hide a legitimate link in the web application, and display another one at its place which redirects to a fake web site.
|
||||
|
||||
|
@ -847,7 +847,7 @@ s = sanitize(user_input, :tags => tags, :attributes => %w(href title))
|
|||
|
||||
This allows only the given tags and does a good job, even against all kinds of tricks and malformed tags.
|
||||
|
||||
As a second step, _(highlight)it is good practice to escape all output of the application_, especially when re-displaying user input, which hasn't been input-filtered (as in the search form example earlier on). _(highlight)Use `escapeHTML()` (or its alias `h()`) method_ to replace the HTML input characters &, ", <, > by their uninterpreted representations in HTML (`&amp;`, `&quot;`, `&lt`;, and `&gt;`). However, it can easily happen that the programmer forgets to use it, so <em class="highlight">it is recommended to use the "SafeErb":http://safe-erb.rubyforge.org/svn/plugins/safe_erb/ plugin</em>. SafeErb reminds you to escape strings from external sources.
|
||||
As a second step, _(highlight)it is good practice to escape all output of the application_, especially when re-displaying user input, which hasn't been input-filtered (as in the search form example earlier on). _(highlight)Use `escapeHTML()` (or its alias `h()`) method_ to replace the HTML input characters &, ", <, > by their uninterpreted representations in HTML (`&amp;`, `&quot;`, `&lt`;, and `&gt;`). However, it can easily happen that the programmer forgets to use it, so <em class=[highlight">it is recommended to use the "SafeErb](http://safe-erb.rubyforge.org/svn/plugins/safe_erb/) plugin</em>. SafeErb reminds you to escape strings from external sources.
|
||||
|
||||
##### Obfuscation and Encoding Injection
|
||||
|
||||
|
@ -858,13 +858,13 @@ Network traffic is mostly based on the limited Western alphabet, so new characte
|
|||
&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;>
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
#### Examples from the Underground
|
||||
|
||||
_In order to understand today's attacks on web applications, it's best to take a look at some real-world attack vectors._
|
||||
|
||||
The following is an excerpt from the "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:
|
||||
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
|
||||
<img src='http://us.i1.yimg.com/us.yimg.com/i/us/nt/ma/ma_mail_1.gif'
|
||||
|
@ -874,9 +874,9 @@ The following is an excerpt from the "Js.Yamanner@m":http://www.symantec.com/sec
|
|||
|
||||
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.
|
||||
|
||||
Another proof-of-concept webmail worm is Nduja, a cross-domain worm for four Italian webmail services. Find more details on "Rosario Valotta's paper":http://www.xssed.com/article/9/Paper_A_PoC_of_a_cross_webmail_worm_XWW_called_Njuda_connection/. Both webmail worms have the goal to harvest email addresses, something a criminal hacker could make money with.
|
||||
Another proof-of-concept webmail worm is Nduja, a cross-domain worm for four Italian webmail services. Find more details on [Rosario Valotta's paper](http://www.xssed.com/article/9/Paper_A_PoC_of_a_cross_webmail_worm_XWW_called_Njuda_connection/). Both webmail worms have the goal to harvest email addresses, something a criminal hacker could make money with.
|
||||
|
||||
In December 2006, 34,000 actual user names and passwords were stolen in a "MySpace phishing attack":http://news.netcraft.com/archives/2006/10/27/myspace_accounts_compromised_by_phishers.html. The idea of the attack was to create a profile page named “login_home_index_html”, so the URL looked very convincing. Specially-crafted HTML and CSS was used to hide the genuine MySpace content from the page and instead display its own login form.
|
||||
In December 2006, 34,000 actual user names and passwords were stolen in a [MySpace phishing attack](http://news.netcraft.com/archives/2006/10/27/myspace_accounts_compromised_by_phishers.html). The idea of the attack was to create a profile page named “login_home_index_html”, so the URL looked very convincing. Specially-crafted HTML and CSS was used to hide the genuine MySpace content from the page and instead display its own login form.
|
||||
|
||||
The MySpace Samy worm will be discussed in the CSS Injection section.
|
||||
|
||||
|
@ -884,7 +884,7 @@ The MySpace Samy worm will be discussed in the CSS Injection section.
|
|||
|
||||
INFO: _CSS Injection is actually JavaScript injection, because some browsers (IE, some versions of Safari and others) allow JavaScript in CSS. Think twice about allowing custom CSS in your web application._
|
||||
|
||||
CSS Injection is explained best by a well-known worm, the "MySpace Samy worm":http://namb.la/popular/tech.html. This worm automatically sent a friend request to Samy (the attacker) simply by visiting his profile. Within several hours he had over 1 million friend requests, but it creates too much traffic on MySpace, so that the site goes offline. The following is a technical explanation of the worm.
|
||||
CSS Injection is explained best by a well-known worm, the [MySpace Samy worm](http://namb.la/popular/tech.html). This worm automatically sent a friend request to Samy (the attacker) simply by visiting his profile. Within several hours he had over 1 million friend requests, but it creates too much traffic on MySpace, so that the site goes offline. The following is a technical explanation of the worm.
|
||||
|
||||
MySpace blocks many tags, however it allows CSS. So the worm's author put JavaScript into CSS like this:
|
||||
|
||||
|
@ -914,7 +914,7 @@ Another problem for the worm's author were CSRF security tokens. Without them he
|
|||
|
||||
In the end, he got a 4 KB worm, which he injected into his profile page.
|
||||
|
||||
The "moz-binding":http://www.securiteam.com/securitynews/5LP051FHPE.html CSS property proved to be another way to introduce JavaScript in CSS in Gecko-based browsers (Firefox, for example).
|
||||
The [moz-binding](http://www.securiteam.com/securitynews/5LP051FHPE.html) CSS property proved to be another way to introduce JavaScript in CSS in Gecko-based browsers (Firefox, for example).
|
||||
|
||||
#### Countermeasures
|
||||
|
||||
|
@ -922,9 +922,9 @@ This example, again, showed that a blacklist filter is never complete. However,
|
|||
|
||||
### Textile Injection
|
||||
|
||||
If you want to provide text formatting other than HTML (due to security), use a mark-up language which is converted to HTML on the server-side. "RedCloth":http://redcloth.org/ is such a language for Ruby, but without precautions, it is also vulnerable to XSS.
|
||||
If you want to provide text formatting other than HTML (due to security), use a mark-up language which is converted to HTML on the server-side. [RedCloth](http://redcloth.org/) is such a language for Ruby, but without precautions, it is also vulnerable to XSS.
|
||||
|
||||
For example, RedCloth translates `_test_` to <em>test<em>, which makes the text italic. However, up to the current version 3.0.4, it is still vulnerable to XSS. 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:
|
||||
For example, RedCloth translates `_test_` to <em>test<em>, which makes the text italic. However, up to the current version 3.0.4, it is still vulnerable to XSS. 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
|
||||
RedCloth.new('<script>alert(1)</script>').to_html
|
||||
|
@ -953,7 +953,7 @@ It is recommended to _(highlight)use RedCloth in combination with a whitelist in
|
|||
|
||||
NOTE: _The same security precautions have to be taken for Ajax actions as for “normal” ones. There is at least one exception, however: The output has to be escaped in the controller already, if the action doesn't render a view._
|
||||
|
||||
If you use the "in_place_editor plugin":http://dev.rubyonrails.org/browser/plugins/in_place_editing, or actions that return a string, rather than rendering a view, _(highlight)you have to escape the return value in the action_. Otherwise, if the return value contains a XSS string, the malicious code will be executed upon return to the browser. Escape any input value using the h() method.
|
||||
If you use the [in_place_editor plugin](http://dev.rubyonrails.org/browser/plugins/in_place_editing), or actions that return a string, rather than rendering a view, _(highlight)you have to escape the return value in the action_. Otherwise, if the return value contains a XSS string, the malicious code will be executed upon return to the browser. Escape any input value using the h() method.
|
||||
|
||||
### Command Line Injection
|
||||
|
||||
|
@ -1064,18 +1064,18 @@ _'1; mode=block' in Rails by default_ - use XSS Auditor and block page if XSS at
|
|||
* X-Content-Type-Options
|
||||
_'nosniff' in Rails by default_ - stops the browser from guessing the MIME type of a file.
|
||||
* X-Content-Security-Policy
|
||||
"A powerful mechanism for controlling which sites certain content types can be loaded from":http://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html
|
||||
[A powerful mechanism for controlling which sites certain content types can be loaded from](http://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html)
|
||||
* Access-Control-Allow-Origin
|
||||
Used to control which sites are allowed to bypass same origin policies and send cross-origin requests.
|
||||
* Strict-Transport-Security
|
||||
"Used to control if the browser is allowed to only access a site over a secure connection":http://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security
|
||||
[Used to control if the browser is allowed to only access a site over a secure connection](http://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security)
|
||||
|
||||
Additional Resources
|
||||
--------------------
|
||||
|
||||
The security landscape shifts and it is important to keep up to date, because missing a new vulnerability can be catastrophic. You can find additional resources about (Rails) security here:
|
||||
|
||||
* The Ruby on Rails security project posts security news regularly: "http://www.rorsecurity.info":http://www.rorsecurity.info
|
||||
* Subscribe to the Rails security "mailing list":http://groups.google.com/group/rubyonrails-security
|
||||
* "Keep up to date on the other application layers":http://secunia.com/ (they have a weekly newsletter, too)
|
||||
* A "good security blog":http://ha.ckers.org/blog/ including the "Cross-Site scripting Cheat Sheet":http://ha.ckers.org/xss.html
|
||||
* The Ruby on Rails security project posts security news regularly: [http://www.rorsecurity.info](http://www.rorsecurity.info)
|
||||
* Subscribe to the Rails security [mailing list](http://groups.google.com/group/rubyonrails-security)
|
||||
* [Keep up to date on the other application layers](http://secunia.com/) (they have a weekly newsletter, too)
|
||||
* A [good security blog](http://ha.ckers.org/blog/) including the [Cross-Site scripting Cheat Sheet](http://ha.ckers.org/xss.html)
|
||||
|
|
|
@ -119,7 +119,7 @@ In Rails, unit tests are what you write to test your models.
|
|||
|
||||
For this guide we will be using Rails _scaffolding_. It will create the model, a migration, controller and views for the new resource in a single operation. It will also create a full test suite following Rails best practices. I will be using examples from this generated code and will be supplementing it with additional examples where necessary.
|
||||
|
||||
NOTE: For more information on Rails <i>scaffolding</i>, refer to "Getting Started with Rails":getting_started.html
|
||||
NOTE: For more information on Rails <i>scaffolding</i>, refer to [Getting Started with Rails](getting_started.html)
|
||||
|
||||
When you use `rails generate scaffold`, for a resource among other things it creates a test stub in the `test/unit` folder:
|
||||
|
||||
|
@ -316,7 +316,7 @@ Finished in 0.193608 seconds.
|
|||
|
||||
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).
|
||||
|
||||
TIP: Many Rails developers practice _Test-Driven Development_ (TDD). This is an excellent way to build up a test suite that exercises every part of your application. TDD is beyond the scope of this guide, but one place to start is with "15 TDD steps to create a Rails application":http://andrzejonsoftware.blogspot.com/2007/05/15-tdd-steps-to-create-rails.html.
|
||||
TIP: Many Rails developers practice _Test-Driven Development_ (TDD). This is an excellent way to build up a test suite that exercises every part of your application. TDD is beyond the scope of this guide, but one place to start is with [15 TDD steps to create a Rails application](http://andrzejonsoftware.blogspot.com/2007/05/15-tdd-steps-to-create-rails.html).
|
||||
|
||||
To see how an error gets reported, here's a test containing an error:
|
||||
|
||||
|
@ -601,7 +601,7 @@ assert_select "ol" do
|
|||
end
|
||||
```
|
||||
|
||||
The `assert_select` assertion is quite powerful. For more advanced usage, refer to its "documentation":http://api.rubyonrails.org/classes/ActionDispatch/Assertions/SelectorAssertions.html.
|
||||
The `assert_select` assertion is quite powerful. For more advanced usage, refer to its [documentation](http://api.rubyonrails.org/classes/ActionDispatch/Assertions/SelectorAssertions.html).
|
||||
|
||||
#### Additional View-Based Assertions
|
||||
|
||||
|
@ -770,7 +770,7 @@ Brief Note About `Test::Unit`
|
|||
Ruby ships with a boat load of libraries. One little gem of a library is `Test::Unit`, a framework for unit testing in Ruby. All the basic assertions discussed above are actually defined in `Test::Unit::Assertions`. The class `ActiveSupport::TestCase` which we have been using in our unit and functional tests extends `Test::Unit::TestCase`, allowing
|
||||
us to use all of the basic assertions in our tests.
|
||||
|
||||
NOTE: For more information on `Test::Unit`, refer to "test/unit Documentation":http://ruby-doc.org/stdlib/libdoc/test/unit/rdoc/
|
||||
NOTE: For more information on `Test::Unit`, refer to [test/unit Documentation](http://ruby-doc.org/stdlib/libdoc/test/unit/rdoc/)
|
||||
|
||||
Setup and Teardown
|
||||
------------------
|
||||
|
@ -964,8 +964,8 @@ Other Testing Approaches
|
|||
|
||||
The built-in `test/unit` based testing is not the only way to test Rails applications. Rails developers have come up with a wide variety of other approaches and aids for testing, including:
|
||||
|
||||
* "NullDB":http://avdi.org/projects/nulldb/, a way to speed up testing by avoiding database use.
|
||||
* "Factory Girl":https://github.com/thoughtbot/factory_girl/tree/master, a replacement for fixtures.
|
||||
* "Machinist":https://github.com/notahat/machinist/tree/master, another replacement for fixtures.
|
||||
* "Shoulda":http://www.thoughtbot.com/projects/shoulda, an extension to `test/unit` with additional helpers, macros, and assertions.
|
||||
* "RSpec":http://relishapp.com/rspec, a behavior-driven development framework
|
||||
* [NullDB](http://avdi.org/projects/nulldb/), a way to speed up testing by avoiding database use.
|
||||
* [Factory Girl](https://github.com/thoughtbot/factory_girl/tree/master), a replacement for fixtures.
|
||||
* [Machinist](https://github.com/notahat/machinist/tree/master), another replacement for fixtures.
|
||||
* [Shoulda](http://www.thoughtbot.com/projects/shoulda), an extension to `test/unit` with additional helpers, macros, and assertions.
|
||||
* [RSpec](http://relishapp.com/rspec), a behavior-driven development framework
|
||||
|
|
|
@ -39,13 +39,13 @@ Rails 4.0 no longer supports loading plugins from `vendor/plugins`. You must rep
|
|||
|
||||
### Identity Map
|
||||
|
||||
Rails 4.0 has removed the identity map from Active Record, due to "some inconsistencies with associations":https://github.com/rails/rails/commit/302c912bf6bcd0fa200d964ec2dc4a44abe328a6. If you have manually enabled it in your application, you will have to remove the following config that has no effect anymore: `config.active_record.identity_map`.
|
||||
Rails 4.0 has removed the identity map from Active Record, due to [some inconsistencies with associations](https://github.com/rails/rails/commit/302c912bf6bcd0fa200d964ec2dc4a44abe328a6). If you have manually enabled it in your application, you will have to remove the following config that has no effect anymore: `config.active_record.identity_map`.
|
||||
|
||||
### Active Record
|
||||
|
||||
The `delete` method in collection associations can now receive `Fixnum` or `String` arguments as record ids, besides records, pretty much like the `destroy` method does. Previously it raised `ActiveRecord::AssociationTypeMismatch` for such arguments. From Rails 4.0 on `delete` automatically tries to find the records matching the given ids before deleting them.
|
||||
|
||||
Rails 4.0 has changed how orders get stacked in `ActiveRecord::Relation`. In previous versions of rails new order was applied after previous defined order. But this is no long true. Check "ActiveRecord Query guide":active_record_querying.html#ordering for more information.
|
||||
Rails 4.0 has changed how orders get stacked in `ActiveRecord::Relation`. In previous versions of rails new order was applied after previous defined order. But this is no long true. Check [ActiveRecord Query guide](active_record_querying.html#ordering) for more information.
|
||||
|
||||
Rails 4.0 has changed `serialized_attributes` and `attr_readonly` to class methods only. Now you shouldn't use instance methods, it's deprecated. You must change them, e.g. `self.serialized_attributes` to `self.class.serialized_attributes`.
|
||||
|
||||
|
@ -182,7 +182,7 @@ config.assets.debug = true
|
|||
|
||||
### 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.
|
||||
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
|
||||
# Compress JavaScripts and CSS
|
||||
|
|
Loading…
Reference in a new issue