aboutsummaryrefslogtreecommitdiffstats
path: root/railties/guides/source
diff options
context:
space:
mode:
Diffstat (limited to 'railties/guides/source')
-rw-r--r--railties/guides/source/2_3_release_notes.textile2
-rw-r--r--railties/guides/source/action_controller_overview.textile58
-rw-r--r--railties/guides/source/action_mailer_basics.textile6
-rw-r--r--railties/guides/source/action_view_overview.textile417
-rw-r--r--railties/guides/source/active_record_querying.textile45
-rw-r--r--railties/guides/source/active_record_validations_callbacks.textile22
-rw-r--r--railties/guides/source/active_support_core_extensions.textile70
-rw-r--r--railties/guides/source/ajax_on_rails.textile147
-rw-r--r--railties/guides/source/api_documentation_guidelines.textile2
-rw-r--r--railties/guides/source/association_basics.textile31
-rw-r--r--railties/guides/source/caching_with_rails.textile12
-rw-r--r--railties/guides/source/command_line.textile15
-rw-r--r--railties/guides/source/configuring.textile6
-rw-r--r--railties/guides/source/contributing_to_ruby_on_rails.textile73
-rw-r--r--railties/guides/source/debugging_rails_applications.textile61
-rw-r--r--railties/guides/source/form_helpers.textile6
-rw-r--r--railties/guides/source/generators.textile4
-rw-r--r--railties/guides/source/getting_started.textile111
-rw-r--r--railties/guides/source/i18n.textile16
-rw-r--r--railties/guides/source/index.html.erb2
-rw-r--r--railties/guides/source/initialization.textile25
-rw-r--r--railties/guides/source/layout.html.erb2
-rw-r--r--railties/guides/source/layouts_and_rendering.textile38
-rw-r--r--railties/guides/source/migrations.textile98
-rw-r--r--railties/guides/source/plugins.textile46
-rw-r--r--railties/guides/source/rails_application_templates.textile44
-rw-r--r--railties/guides/source/routing.textile10
-rw-r--r--railties/guides/source/ruby_on_rails_guides_guidelines.textile17
-rw-r--r--railties/guides/source/security.textile65
-rw-r--r--railties/guides/source/testing.textile16
30 files changed, 699 insertions, 768 deletions
diff --git a/railties/guides/source/2_3_release_notes.textile b/railties/guides/source/2_3_release_notes.textile
index 67743a4797..15abba66ab 100644
--- a/railties/guides/source/2_3_release_notes.textile
+++ b/railties/guides/source/2_3_release_notes.textile
@@ -410,7 +410,7 @@ You're likely familiar with Rails' practice of adding timestamps to static asset
h4. Asset Hosts as Objects
-Asset hosts get more flexible in edge Rails with the ability to declare an asset host as a specific object that responds to a call. This allows you to to implement any complex logic you need in your asset hosting.
+Asset hosts get more flexible in edge Rails with the ability to declare an asset host as a specific object that responds to a call. This allows you to implement any complex logic you need in your asset hosting.
* More Information: "asset-hosting-with-minimum-ssl":http://github.com/dhh/asset-hosting-with-minimum-ssl/tree/master
diff --git a/railties/guides/source/action_controller_overview.textile b/railties/guides/source/action_controller_overview.textile
index 178d98c2d6..3a1a4ee66e 100644
--- a/railties/guides/source/action_controller_overview.textile
+++ b/railties/guides/source/action_controller_overview.textile
@@ -368,7 +368,7 @@ class UsersController < ApplicationController
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @users}
- format.json { render :json => @users}
+ format.json { render :json => @users}
end
end
end
@@ -488,45 +488,6 @@ end
Again, this is not an ideal example for this filter, because it's not run in the scope of the controller but gets the controller passed as an argument. The filter class has a class method +filter+ which gets run before or after the action, depending on if it's a before or after filter. Classes used as around filters can also use the same +filter+ method, which will get run in the same way. The method must +yield+ to execute the action. Alternatively, it can have both a +before+ and an +after+ method that are run before and after the action.
-h3. Verification
-
-Verifications make sure certain criteria are met in order for a controller or action to run. They can specify that a certain key (or several keys in the form of an array) is present in the +params+, +session+ or +flash+ hashes or that a certain HTTP method was used or that the request was made using +XMLHttpRequest+ (Ajax). The default action taken when these criteria are not met is to render a 400 Bad Request response, but you can customize this by specifying a redirect URL or rendering something else and you can also add flash messages and HTTP headers to the response.
-
-Here's an example of using verification to make sure the user supplies a username and a password in order to log in:
-
-<ruby>
-class LoginsController < ApplicationController
- verify :params => [:username, :password],
- :render => {:action => "new"},
- :add_flash => {
- :error => "Username and password required to log in"
- }
-
- def create
- @user = User.authenticate(params[:username], params[:password])
- if @user
- flash[:notice] = "You're logged in"
- redirect_to root_url
- else
- render :action => "new"
- end
- end
-end
-</ruby>
-
-Now the +create+ action won't run unless the "username" and "password" parameters are present, and if they're not, an error message will be added to the flash and the +new+ action will be rendered. But there's something rather important missing from the verification above: It will be used for *every* action in LoginsController, which is not what we want. You can limit which actions it will be used for with the +:only+ and +:except+ options just like a filter:
-
-<ruby>
-class LoginsController < ApplicationController
- verify :params => [:username, :password],
- :render => {:action => "new"},
- :add_flash => {
- :error => "Username and password required to log in"
- },
- :only => :create # Run only for the "create" action
-end
-</ruby>
-
h3. Request Forgery Protection
Cross-site request forgery is a type of attack in which a site tricks a user into making requests on another site, possibly adding, modifying or deleting data on that site without the user's knowledge or permission.
@@ -615,26 +576,15 @@ Rails comes with two built-in HTTP authentication mechanisms:
h4. HTTP Basic Authentication
-HTTP basic authentication is an authentication scheme that is supported by the majority of browsers and other HTTP clients. As an example, consider an administration section which will only be available by entering a username and a password into the browser's HTTP basic dialog window. Using the built-in authentication is quite easy and only requires you to use one method, +authenticate_or_request_with_http_basic+.
+HTTP basic authentication is an authentication scheme that is supported by the majority of browsers and other HTTP clients. As an example, consider an administration section which will only be available by entering a username and a password into the browser's HTTP basic dialog window. Using the built-in authentication is quite easy and only requires you to use one method, +http_basic_authenticate_with+.
<ruby>
class AdminController < ApplicationController
- USERNAME, PASSWORD = "humbaba", "5baa61e4"
-
- before_filter :authenticate
-
- private
-
- def authenticate
- authenticate_or_request_with_http_basic do |username, password|
- username == USERNAME &&
- Digest::SHA1.hexdigest(password) == PASSWORD
- end
- end
+ http_basic_authenticate_with :name => "humbaba", :password => "5baa61e4"
end
</ruby>
-With this in place, you can create namespaced controllers that inherit from +AdminController+. The before filter will thus be run for all actions in those controllers, protecting them with HTTP basic authentication.
+With this in place, you can create namespaced controllers that inherit from +AdminController+. The filter will thus be run for all actions in those controllers, protecting them with HTTP basic authentication.
h4. HTTP Digest Authentication
diff --git a/railties/guides/source/action_mailer_basics.textile b/railties/guides/source/action_mailer_basics.textile
index 56da360972..a6ff8f877d 100644
--- a/railties/guides/source/action_mailer_basics.textile
+++ b/railties/guides/source/action_mailer_basics.textile
@@ -120,7 +120,7 @@ Now that we have a user model to play with, we will just edit the +app/controlle
<ruby>
class UsersController < ApplicationController
# POST /users
- # POST /users.xml
+ # POST /users.json
def create
@user = User.new(params[:user])
@@ -130,10 +130,10 @@ class UsersController < ApplicationController
UserMailer.welcome_email(@user).deliver
format.html { redirect_to(@user, :notice => 'User was successfully created.') }
- format.xml { render :xml => @user, :status => :created, :location => @user }
+ format.json { render :json => @user, :status => :created, :location => @user }
else
format.html { render :action => "new" }
- format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
+ format.json { render :json => @user.errors, :status => :unprocessable_entity }
end
end
end
diff --git a/railties/guides/source/action_view_overview.textile b/railties/guides/source/action_view_overview.textile
index cfd71ad287..2b2c197f46 100644
--- a/railties/guides/source/action_view_overview.textile
+++ b/railties/guides/source/action_view_overview.textile
@@ -20,7 +20,28 @@ Note: Some features of Action View are tied to Active Record, but that doesn't m
h3. Using Action View with Rails
-TODO...
+For each controller there is an associated directory in the <tt>app/views</tt> directory which holds the template files that make up the views associated with that controller. These files are used to display the view that results from each controller action.
+
+Let's take a look at what Rails does by default when creating a new resource using the scaffold generator:
+
+<shell>
+$ rails generate scaffold post
+ [...]
+ invoke scaffold_controller
+ create app/controllers/posts_controller.rb
+ invoke erb
+ create app/views/posts
+ create app/views/posts/index.html.erb
+ create app/views/posts/edit.html.erb
+ create app/views/posts/show.html.erb
+ create app/views/posts/new.html.erb
+ create app/views/posts/_form.html.erb
+ [...]
+</shell>
+
+There is a naming convention for views in Rails. Typically, the views share their name with the associated controller action, as you can see above.
+For example, the index controller action of the <tt>posts_controller.rb</tt> will use the <tt>index.html.erb</tt> view file in the <tt>app/views/posts</tt> directory.
+The complete HTML returned to the client is composed of a combination of this ERB file, a layout template that wraps it, and all the partials that the view may reference. Later on this guide you can find a more detailed documentation of each one of this three components.
h3. Using Action View outside of Rails
@@ -94,9 +115,213 @@ TODO needs a screenshot? I have one - not sure where to put it.
h3. Templates, Partials and Layouts
-TODO...
+As mentioned before, the final HTML output is a composition of three Rails elements: +Templates+, +Partials+ and +Layouts+.
+Find below a brief overview of each one of them.
+
+h4. Templates
+
+Action View templates can be written in several ways. If the template file has a <tt>.erb</tt> extension then it uses a mixture of ERB (included in Ruby) and HTML. If the template file has a <tt>.builder</tt> extension then a fresh instance of <tt>Builder::XmlMarkup</tt> library is used.
+
+Rails supports multiple template systems and uses a file extension to distinguish amongst them. For example, an HTML file using the ERB template system will have <tt>.html.erb</tt> as a file extension.
+
+h5. ERB
+
+Within an ERB template Ruby code can be included using both +<% %>+ and +<%= %>+ tags. The +<% %>+ are used to execute Ruby code that does not return anything, such as conditions, loops or blocks, and the +<%= %>+ tags are used when you want output.
+
+Consider the following loop for names:
+
+<erb>
+<b>Names of all the people</b>
+<% @people.each do |person| %>
+ Name: <%= person.name %><br/>
+<% end %>
+</erb>
+
+The loop is setup in regular embedding tags +<% %>+ and the name is written using the output embedding tag +<%= %>+. Note that this is not just a usage suggestion, for Regular output functions like print or puts won't work with ERB templates. So this would be wrong:
+
+<erb>
+<%# WRONG %>
+Hi, Mr. <% puts "Frodo" %>
+</erb>
+
+To suppress leading and trailing whitespaces, you can use +<%-+ +-%>+ interchangeably with +<%+ and +%>+.
+
+h5. Builder
+
+Builder templates are a more programmatic alternative to ERB. They are especially useful for generating XML content. An XmlMarkup object named +xml+ is automatically made available to templates with a <tt>.builder</tt> extension.
+
+Here are some basic examples:
+
+<ruby>
+xml.em("emphasized")
+xml.em { xml.b("emph & bold") }
+xml.a("A Link", "href"=>"http://rubyonrails.org")
+xml.target("name"=>"compile", "option"=>"fast")
+</ruby>
+
+will produce
-TODO see http://guides.rubyonrails.org/layouts_and_rendering.html
+<html>
+<em>emphasized</em>
+<em><b>emph &amp; bold</b></em>
+<a href="http://rubyonrails.org">A link</a>
+<target option="fast" name="compile" \>
+</html>
+
+Any method with a block will be treated as an XML markup tag with nested markup in the block. For example, the following:
+
+<ruby>
+xml.div {
+ xml.h1(@person.name)
+ xml.p(@person.bio)
+}
+</ruby>
+
+would produce something like:
+
+<html>
+<div>
+ <h1>David Heinemeier Hansson</h1>
+ <p>A product of Danish Design during the Winter of '79...</p>
+</div>
+</html>
+
+A full-length RSS example actually used on Basecamp:
+
+<ruby>
+xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/") do
+ xml.channel do
+ xml.title(@feed_title)
+ xml.link(@url)
+ xml.description "Basecamp: Recent items"
+ xml.language "en-us"
+ xml.ttl "40"
+
+ for item in @recent_items
+ xml.item do
+ xml.title(item_title(item))
+ xml.description(item_description(item)) if item_description(item)
+ xml.pubDate(item_pubDate(item))
+ xml.guid(@person.firm.account.url + @recent_items.url(item))
+ xml.link(@person.firm.account.url + @recent_items.url(item))
+ xml.tag!("dc:creator", item.author_name) if item_has_creator?(item)
+ end
+ end
+ end
+end
+</ruby>
+
+h5. Template caching
+
+By default, Rails will compile each template to a method in order to render it. When you alter a template, Rails will check the file's modification time and recompile it in development mode.
+
+h4. Partials
+
+Partial templates – usually just called "partials" – are another device for breaking the rendering process into more manageable chunks. With a partial, you can move the code for rendering a particular piece of a response to its own file.
+
+h5. Naming Partials
+
+To render a partial as part of a view, you use the +render+ method within the view:
+
+<ruby>
+<%= render "menu" %>
+</ruby>
+
+This will render a file named +_menu.html.erb+ at that point within the view is being rendered. Note the leading underscore character: partials are named with a leading underscore to distinguish them from regular views, even though they are referred to without the underscore. This holds true even when you're pulling in a partial from another folder:
+
+<ruby>
+<%= render "shared/menu" %>
+</ruby>
+
+That code will pull in the partial from +app/views/shared/_menu.html.erb+.
+
+h5. Using Partials to Simplify Views
+
+One way to use partials is to treat them as the equivalent of subroutines: as a way to move details out of a view so that you can grasp what's going on more easily. For example, you might have a view that looked like this:
+
+<erb>
+<%= render "shared/ad_banner" %>
+
+<h1>Products</h1>
+
+<p>Here are a few of our fine products:</p>
+<% @products.each do |product| %>
+ <%= render :partial => "product", :locals => { :product => product } %>
+<% end %>
+
+<%= render "shared/footer" %>
+</erb>
+
+Here, the +_ad_banner.html.erb+ and +_footer.html.erb+ partials could contain content that is shared among many pages in your application. You don't need to see the details of these sections when you're concentrating on a particular page.
+
+h5. The :as and :object options
+
+By default <tt>ActionView::Partials::PartialRenderer</tt> has its object in a local variable with the same name as the template. So, given
+
+<erb>
+<%= render :partial => "product" %>
+</erb>
+
+within product we'll get <tt>@product</tt> in the local variable +product+, as if we had written:
+
+<erb>
+<%= render :partial => "product", :locals => { :product => @product } %>
+</erb>
+
+With the <tt>:as</tt> option we can specify a different name for said local variable. For example, if we wanted it to be +item+ instead of product+ we'd do:
+
+<erb>
+<%= render :partial => "product", :as => 'item' %>
+</erb>
+
+The <tt>:object</tt> option can be used to directly specify which object is rendered into the partial; useful when the template's object is elsewhere, in a different ivar or in a local variable for instance.
+
+For example, instead of:
+
+<erb>
+<%= render :partial => "product", :locals => { :product => @item } %>
+</erb>
+
+you'd do:
+
+<erb>
+<%= render :partial => "product", :object => @item %>
+</erb>
+
+The <tt>:object</tt> and <tt>:as</tt> options can be used together.
+
+h5. Rendering Collections
+
+The example of partial use describes a familiar pattern where a template needs to iterate over an array and render a sub template for each of the elements. This pattern has been implemented as a single method that accepts an array and renders a partial by the same name as the elements contained within.
+So the three-lined example for rendering all the products can be rewritten with a single line:
+
+<erb>
+<%= render :partial => "product", :collection => @products %>
+</erb>
+
+When a partial is called with a pluralized collection, then the individual instances of the partial have access to the member of the collection being rendered via a variable named after the partial. In this case, the partial is +_product+ , and within the +_product+ partial, you can refer to +product+ to get the instance that is being rendered.
+
+You can use a shorthand syntax for rendering collections. Assuming @products is a collection of +Product+ instances, you can simply write the following to produce the same result:
+
+<erb>
+<%= render @products %>
+</erb>
+
+Rails determines the name of the partial to use by looking at the model name in the collection. In fact, you can even create a heterogeneous collection and render it this way, and Rails will choose the proper partial for each member of the collection.
+
+h5. Spacer Templates
+
+You can also specify a second partial to be rendered between instances of the main partial by using the +:spacer_template+ option:
+
+<erb>
+<%= render @products, :spacer_template => "product_ruler" %>
+</erb>
+
+Rails will render the +_product_ruler+ partial (with no data passed in to it) between each pair of +_product+ partials.
+
+h4. Layouts
+
+TODO...
h3. Using Templates, Partials and Layouts in "The Rails Way"
@@ -262,9 +487,9 @@ Register one or more stylesheet files to be included when symbol is passed to +s
ActionView::Helpers::AssetTagHelper.register_stylesheet_expansion :monkey => ["head", "body", "tail"]
stylesheet_link_tag :monkey # =>
- <link href="/stylesheets/head.css" media="screen" rel="stylesheet" type="text/css" />
- <link href="/stylesheets/body.css" media="screen" rel="stylesheet" type="text/css" />
- <link href="/stylesheets/tail.css" media="screen" rel="stylesheet" type="text/css" />
+ <link href="/stylesheets/head.css" media="screen" rel="stylesheet" type="text/css" />
+ <link href="/stylesheets/body.css" media="screen" rel="stylesheet" type="text/css" />
+ <link href="/stylesheets/tail.css" media="screen" rel="stylesheet" type="text/css" />
</ruby>
h5. auto_discovery_link_tag
@@ -301,7 +526,7 @@ javascript_include_tag "common" # =>
<script type="text/javascript" src="/javascripts/common.js"></script>
</ruby>
-To include the Prototype and Scriptaculous JavaScript libraries in your application, pass +:defaults+ as the source. When using +:defaults+, if an +application.js+ file exists in your +public/javascripts+ directory, it will be included as well.
+If the application does not use the asset pipeline, to include the jQuery JavaScript library in your application, pass +:defaults+ as the source. When using +:defaults+, if an +application.js+ file exists in your +public/javascripts+ directory, it will be included as well.
<ruby>
javascript_include_tag :defaults
@@ -1076,8 +1301,6 @@ h4. JavaScriptHelper
Provides functionality for working with JavaScript in your views.
-Rails includes the Prototype JavaScript framework and the Scriptaculous JavaScript controls and visual effects library. If you wish to use these libraries and their helpers, make sure +&lt;%= javascript_include_tag :defaults, :cache => true %&gt;+ is in the HEAD section of your page. This function will include the necessary JavaScript files Rails generated in the +public/javascripts+ directory.
-
h5. button_to_function
Returns a button that'll trigger a JavaScript function using the onclick handler. Examples:
@@ -1177,16 +1400,6 @@ number_with_precision(111.2345) # => 111.235
number_with_precision(111.2345, 2) # => 111.23
</ruby>
-h4. PrototypeHelper
-
-Prototype is a JavaScript library that provides DOM manipulation, Ajax functionality, and more traditional object-oriented facilities for JavaScript. This module provides a set of helpers to make it more convenient to call functions from Prototype using Rails, including functionality to call remote Rails methods (that is, making a background request to a Rails action) using Ajax.
-
-To be able to use these helpers, you must first include the Prototype JavaScript framework in the HEAD of the pages with Prototype functions.
-
-<ruby>
-javascript_include_tag 'prototype'
-</ruby>
-
h5. evaluate_remote_response
Returns +eval(request.responseText)+ which is the JavaScript function that form_remote_tag can call in +:complete+ to evaluate a multiple update return document using +update_element_function+ calls.
@@ -1283,171 +1496,6 @@ would generate:
return false;" type="button" value="Create" />
</html>
-h5. update_page
-
-Yields a JavaScriptGenerator and returns the generated JavaScript code. Use this to update multiple elements on a page in an Ajax response.
-
-<ruby>
-update_page do |page|
- page.hide 'spinner'
-end
-</ruby>
-
-h5. update_page_tag
-
-Works like update_page but wraps the generated JavaScript in a +script+ tag. Use this to include generated JavaScript in an ERb template.
-
-h4. PrototypeHelper::JavaScriptGenerator::GeneratorMethods
-
-JavaScriptGenerator generates blocks of JavaScript code that allow you to change the content and presentation of multiple DOM elements. Use this in your Ajax response bodies, either in a +script+ tag or as plain JavaScript sent with a Content-type of "text/javascript".
-
-h5(#push). <<
-
-Writes raw JavaScript to the page.
-
-<ruby>
-page << "alert('JavaScript with Prototype.');"
-</ruby>
-
-h5(#at). []
-
-Returns a element reference by finding it through it's id in the DOM.
-
-<ruby>
-page['blank_slate'].show # => $('blank_slate').show();
-</ruby>
-
-h5. alert
-
-Displays an alert dialog with the given message.
-
-<ruby>
-page.alert('This message is from Rails!')
-</ruby>
-
-h5. assign
-
-Assigns the JavaScript variable the given value.
-
-<ruby>
-page.assign 'tabulated_total', @total_from_cart
-</ruby>
-
-h5. call
-
-Calls the JavaScript function, optionally with the given arguments.
-
-<ruby>
-page.call 'Element.replace', 'my_element', "My content to replace with."
-</ruby>
-
-h5. delay
-
-Executes the content of the block after a delay of the number of seconds provided.
-
-<ruby>
-page.delay(20) do
- page.visual_effect :fade, 'notice'
-end
-</ruby>
-
-h5. draggable
-
-Creates a script.aculo.us draggable element. See ActionView::Helpers::ScriptaculousHelper for more information.
-
-h5. drop_receiving
-
-Creates a script.aculo.us drop receiving element. See ActionView::Helpers::ScriptaculousHelper for more information.
-
-h5. hide
-
-Hides the visible DOM elements with the given ids.
-
-<ruby>
-page.hide 'person_29', 'person_9', 'person_0'
-</ruby>
-
-h5. insert_html
-
-Inserts HTML at the specified position relative to the DOM element identified by the given id.
-
-<ruby>
-page.insert_html :bottom, 'my_list', '<li>Last item</li>'
-</ruby>
-
-h5. literal
-
-Returns an object whose to_json evaluates to the code provided. Use this to pass a literal JavaScript expression as an argument to another JavaScriptGenerator method.
-
-h5. redirect_to
-
-Redirects the browser to the given location using JavaScript, in the same form as +url_for+.
-
-<ruby>
-page.redirect_to(:controller => 'accounts', :action => 'new')
-</ruby>
-
-h5. remove
-
-Removes the DOM elements with the given ids from the page.
-
-<ruby>
-page.remove 'person_23', 'person_9', 'person_2'
-</ruby>
-
-h5. replace
-
-Replaces the "outer HTML" (i.e., the entire element, not just its contents) of the DOM element with the given id.
-
-<ruby>
-page.replace 'person-45', :partial => 'person', :object => @person
-</ruby>
-
-h5. replace_html
-
-Replaces the inner HTML of the DOM element with the given id.
-
-<ruby>
-page.replace_html 'person-45', :partial => 'person', :object => @person
-</ruby>
-
-h5(#prototype-select). select
-
-Returns a collection reference by finding it through a CSS pattern in the DOM.
-
-<ruby>
-page.select('p.welcome b').first.hide # => $$('p.welcome b').first().hide();
-</ruby>
-
-h5. show
-
-Shows hidden DOM elements with the given ids.
-
-<ruby>
-page.show 'person_6', 'person_13', 'person_223'
-</ruby>
-
-h5. sortable
-
-Creates a script.aculo.us sortable element. Useful to recreate sortable elements after items get added or deleted. See ActionView::Helpers::ScriptaculousHelper for more information.
-
-h5. toggle
-
-Toggles the visibility of the DOM elements with the given ids. Example:
-
-<ruby>
-page.toggle 'person_14', 'person_12', 'person_23' # Hides the elements
-page.toggle 'person_14', 'person_12', 'person_23' # Shows the previously hidden elements
-</ruby>
-
-h5. visual_effect
-
-Starts a script.aculo.us visual effect. See ActionView::Helpers::ScriptaculousHelper for more information.
-
-
-TODO start from RecordIdentificationHelper
-
-
h3. Localized Views
Action View has the ability render different templates depending on the current locale.
@@ -1472,5 +1520,6 @@ You can read more about the Rails Internationalization (I18n) API "here":i18n.ht
h3. Changelog
+* April 16, 2011: Added 'Using Action View with Rails', 'Templates' and 'Partials' sections. "Sebastian Martinez":http://wyeworks.com
* September 3, 2009: Continuing work by Trevor Turk, leveraging the Action Pack docs and "What's new in Edge Rails":http://ryandaigle.com/articles/2007/8/3/what-s-new-in-edge-rails-partials-get-layouts
* April 5, 2009: Starting work by Trevor Turk, leveraging Mike Gunderloy's docs
diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile
index f3a10b8b92..579a323d57 100644
--- a/railties/guides/source/active_record_querying.textile
+++ b/railties/guides/source/active_record_querying.textile
@@ -56,6 +56,7 @@ The methods are:
* +select+
* +group+
* +order+
+* +reorder+
* +limit+
* +offset+
* +joins+
@@ -418,7 +419,7 @@ SELECT viewable_by, locked FROM clients
Be careful because this also means you're initializing a model object with only the fields that you've selected. If you attempt to access a field that is not in the initialized record you'll receive:
<shell>
-ActiveRecord::MissingAttributeError: missing attribute: <attribute>
+ActiveModel::MissingAttributeError: missing attribute: <attribute>
</shell>
Where +&lt;attribute&gt;+ is the attribute you asked for. The +id+ method will not raise the +ActiveRecord::MissingAttributeError+, so just be careful when working with associations because they need the +id+ method to function properly.
@@ -495,9 +496,9 @@ This will return single order objects for each day, but only for the last month.
h3. Overriding Conditions
-You can specify certain conditions to be excepted by using the +except+ method.
+h4. +except+
-For example:
+You can specify certain conditions to be excepted by using the +except+ method. For example:
<ruby>
Post.where('id > 10').limit(20).order('id asc').except(:order)
@@ -509,9 +510,9 @@ The SQL that would be executed:
SELECT * FROM posts WHERE id > 10 LIMIT 20
</sql>
-You can also override conditions using the +only+ method.
+h4. +only+
-For example:
+You can also override conditions using the +only+ method. For example:
<ruby>
Post.where('id > 10').limit(20).order('id desc').only(:order, :where)
@@ -523,6 +524,32 @@ The SQL that would be executed:
SELECT * FROM posts WHERE id > 10 ORDER BY id DESC
</sql>
+h4. +reorder+
+
+The +reorder+ method overrides the default scope order. For example:
+
+<ruby>
+class Post < ActiveRecord::Base
+ ..
+ ..
+ has_many :comments, :order => 'posted_at DESC'
+end
+
+Post.find(10).comments.reorder('name')
+</ruby>
+
+The SQL that would be executed:
+
+<sql>
+SELECT * FROM posts WHERE id = 10 ORDER BY name
+</sql>
+
+In case the +reorder+ clause is not used, the SQL executed would be:
+
+<sql>
+SELECT * FROM posts WHERE id = 10 ORDER BY posted_at DESC
+</sql>
+
h3. Readonly Objects
Active Record provides +readonly+ method on a relation to explicitly disallow modification or deletion of any of the returned object. Any attempt to alter or destroy a readonly record will not succeed, raising an +ActiveRecord::ReadOnlyRecord+ exception.
@@ -546,7 +573,7 @@ Active Record provides two locking mechanisms:
h4. Optimistic Locking
-Optimistic locking allows multiple users to access the same record for edits, and assumes a minimum of conflicts with the data. It does this by checking whether another process has made changes to a record since it was opened. An +ActiveRecord::StaleObjectError+ exception is thrown if that has occurred and the update is ignored.
+Optimistic locking allows multiple users to access the same record for edits, and assumes a minimum of conflicts with the data. It does this by checking whether another process has made changes to a record since it was opened. An +ActiveRecord::StaleObjectError+ exception is thrown if that has occurred and the update is ignored.
<strong>Optimistic locking column</strong>
@@ -790,7 +817,7 @@ Post.includes(:comments).where("comments.visible", true)
This would generate a query which contains a +LEFT OUTER JOIN+ whereas the +joins+ method would generate one using the +INNER JOIN+ function instead.
<ruby>
- SELECT "posts"."id" AS t0_r0, ... "comments"."updated_at" AS t1_r5 FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id" WHERE (comments.visible)
+ SELECT "posts"."id" AS t0_r0, ... "comments"."updated_at" AS t1_r5 FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id" WHERE (comments.visible = 1)
</ruby>
If there was no +where+ condition, this would generate the normal set of two queries.
@@ -993,7 +1020,7 @@ Client.count
# SELECT count(*) AS count_all FROM clients
</ruby>
-Or on a relation :
+Or on a relation:
<ruby>
Client.where(:first_name => 'Ryan').count
@@ -1060,7 +1087,7 @@ If you want to find the sum of a field for all records in your table you can cal
Client.sum("orders_count")
</ruby>
-For options, please see the parent section, "Calculations":#calculations.
+For options, please see the parent section, "Calculations":#calculations.
h3. Changelog
diff --git a/railties/guides/source/active_record_validations_callbacks.textile b/railties/guides/source/active_record_validations_callbacks.textile
index 514d0322b9..19bd4ad0f1 100644
--- a/railties/guides/source/active_record_validations_callbacks.textile
+++ b/railties/guides/source/active_record_validations_callbacks.textile
@@ -552,6 +552,21 @@ class Account < ActiveRecord::Base
end
</ruby>
+h4. Grouping conditional validations
+
+Sometimes it is useful to have multiple validations use one condition, it can be easily achieved using +with_options+.
+
+<ruby>
+class User < ActiveRecord::Base
+ with_options :if => :is_admin? do |admin|
+ admin.validates_length_of :password, :minimum => 10
+ admin.validates_presence_of :email
+ end
+end
+</ruby>
+
+All validations inside of +with_options+ block will have automatically passed the condition +:if => :is_admin?+
+
h3. Creating Custom Validation Methods
When the built-in validation helpers are not enough for your needs, you can write your own validation methods.
@@ -822,7 +837,7 @@ The selectors to customize the style of error messages are:
* +#errorExplanation p+ - Style for the paragraph that holds the message that appears right below the header of the +div+ element.
* +#errorExplanation ul li+ - Style for the list items with individual error messages.
-Scaffolding for example generates +public/stylesheets/scaffold.css+, which defines the red-based style you saw above.
+Scaffolding for example generates +app/assets/stylesheets/scaffold.css.scss+, which later compiles to +app/assets/stylesheets/scaffold.css+ and defines the red-based style you saw above.
The name of the class and the id can be changed with the +:class+ and +:id+ options, accepted by both helpers.
@@ -882,8 +897,9 @@ The macro-style class methods can also receive a block. Consider using this styl
class User < ActiveRecord::Base
validates_presence_of :login, :email
- before_create {|user| user.name = user.login.capitalize
- if user.name.blank?}
+ before_create do |user|
+ user.name = user.login.capitalize if user.name.blank?
+ end
end
</ruby>
diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile
index 788f528654..f2170e120b 100644
--- a/railties/guides/source/active_support_core_extensions.textile
+++ b/railties/guides/source/active_support_core_extensions.textile
@@ -442,6 +442,20 @@ require_library_or_gem('mysql')
NOTE: Defined in +active_support/core_ext/kernel/requires.rb+.
+h4. +in?+
+
+The predicate +in?+ tests if an object is included in another object. An +ArgumentError+ exception will be raised if the argument passed does not respond to +include?+.
+
+Examples of +in?+:
+
+<ruby>
+1.in?([1,2]) # => true
+"lo".in?("hello") # => true
+25.in?(30..50) # => false
+</ruby>
+
+NOTE: Defined in +active_support/core_ext/object/inclusion.rb+.
+
h3. Extensions to +Module+
h4. +alias_method_chain+
@@ -527,9 +541,9 @@ The default value can be also specified with a block, which is called in the con
<ruby>
class User
attr_accessor :name, :surname
- attr_accessor_with_default(:full_name) {
- [name, surname].compact.join(" ")
- }
+ attr_accessor_with_default(:full_name) do
+ [name, surname].compact.join(" ")
+ end
end
u = User.new
@@ -1209,7 +1223,7 @@ NOTE: Defined in +active_support/core_ext/string/output_safety.rb+.
h4. +squish+
-The method +String#squish+ strips leading and trailing whitespace, and substitutes runs of whitespace with a single space each:
+The method +squish+ strips leading and trailing whitespace, and substitutes runs of whitespace with a single space each:
<ruby>
" \n foo\n\r \t bar \n".squish # => "foo bar"
@@ -1252,6 +1266,15 @@ WARNING: The option +:separator+ can't be a regexp.
NOTE: Defined in +active_support/core_ext/string/filters.rb+.
+h4. +inquiry+
+
+The <tt>inquiry</tt> method converts a string into a +StringInquirer+ object making equality checks prettier.
+
+<ruby>
+"production".inquiry.production? # => true
+"active".inquiry.inactive? # => false
+</ruby>
+
h4. Key-based Interpolation
In Ruby 1.9 the <tt>%</tt> string operator supports key-based interpolation, both formatted and unformatted:
@@ -1973,16 +1996,21 @@ Active Support augments the API of arrays to ease certain ways of accessing them
[].to(7) # => []
</ruby>
-Similarly, +from+ returns the tail from the element at the passed index on:
+Similarly, +from+ returns the tail from the element at the passed index to the end. If the index is greater than the length of the array, it returns an empty array.
<ruby>
%w(a b c d).from(2) # => %w(c d)
-%w(a b c d).from(10) # => nil
+%w(a b c d).from(10) # => []
[].from(0) # => []
</ruby>
The methods +second+, +third+, +fourth+, and +fifth+ return the corresponding element (+first+ is built-in). Thanks to social wisdom and positive constructiveness all around, +forty_two+ is also available.
+<ruby>
+%w(a b c d).third # => c
+%w(a b c d).fifth # => nil
+</ruby>
+
NOTE: Defined in +active_support/core_ext/array/access.rb+.
h4. Random Access
@@ -2078,7 +2106,7 @@ h5. +to_xml+
The method +to_xml+ returns a string containing an XML representation of its receiver:
<ruby>
-Contributor.all(:limit => 2, :order => 'rank ASC').to_xml
+Contributor.limit(2).order(:rank).to_xml
# =>
# <?xml version="1.0" encoding="UTF-8"?>
# <contributors type="array">
@@ -2153,7 +2181,7 @@ The name of children nodes is by default the name of the root node singularized.
The default XML builder is a fresh instance of <tt>Builder::XmlMarkup</tt>. You can configure your own builder via the <tt>:builder</tt> option. The method also accepts options like <tt>:dasherize</tt> and friends, they are forwarded to the builder:
<ruby>
-Contributor.all(:limit => 2, :order => 'rank ASC').to_xml(:skip_types => true)
+Contributor.limit(2).order(:rank).to_xml(:skip_types => true)
# =>
# <?xml version="1.0" encoding="UTF-8"?>
# <contributors>
@@ -3393,11 +3421,11 @@ h4. +silence+
Silences every log level lesser to the specified one for the duration of the given block. Log level orders are: debug, info, error and fatal.
<ruby>
- logger = Logger.new("log/development.log")
- logger.silence(Logger::INFO) do
- logger.debug("In space, no one can hear you scream.")
- logger.info("Scream all you want, small mailman!")
- end
+logger = Logger.new("log/development.log")
+logger.silence(Logger::INFO) do
+ logger.debug("In space, no one can hear you scream.")
+ logger.info("Scream all you want, small mailman!")
+end
</ruby>
h4. +datetime_format=+
@@ -3405,17 +3433,17 @@ h4. +datetime_format=+
Modifies the datetime format output by the formatter class associated with this logger. If the formatter class does not have a +datetime_format+ method then this is ignored.
<ruby>
- class Logger::FormatWithTime < Logger::Formatter
- cattr_accessor(:datetime_format) { "%Y%m%d%H%m%S" }
+class Logger::FormatWithTime < Logger::Formatter
+ cattr_accessor(:datetime_format) { "%Y%m%d%H%m%S" }
- def self.call(severity, timestamp, progname, msg)
- "#{timestamp.strftime(datetime_format)} -- #{String === msg ? msg : msg.inspect}\n"
- end
+ def self.call(severity, timestamp, progname, msg)
+ "#{timestamp.strftime(datetime_format)} -- #{String === msg ? msg : msg.inspect}\n"
end
+end
- logger = Logger.new("log/development.log")
- logger.formatter = Logger::FormatWithTime
- logger.info("<- is the current time")
+logger = Logger.new("log/development.log")
+logger.formatter = Logger::FormatWithTime
+logger.info("<- is the current time")
</ruby>
NOTE: Defined in +active_support/core_ext/logger.rb+.
diff --git a/railties/guides/source/ajax_on_rails.textile b/railties/guides/source/ajax_on_rails.textile
index b80df4aa58..1566c23414 100644
--- a/railties/guides/source/ajax_on_rails.textile
+++ b/railties/guides/source/ajax_on_rails.textile
@@ -3,14 +3,14 @@ h2. AJAX on Rails
This guide covers the built-in Ajax/JavaScript functionality of Rails (and more); it will enable you to create rich and dynamic AJAX applications with ease! We will cover the following topics:
* Quick introduction to AJAX and related technologies
-* Handling JavaScript the Rails way: Rails helpers, RJS, Prototype and script.aculo.us
+* Handling JavaScript the Rails way: Rails helpers, Prototype and script.aculo.us
* Testing JavaScript functionality
endprologue.
h3. Hello AJAX - a Quick Intro
-If you are a 'show me the code' type of person, you might want to skip this part and jump to the RJS section right away. However, I would really recommend to read it - you'll need the basics of DOM, http requests and other topics discussed here to really understand Ajax on Rails.
+You'll need the basics of DOM, HTTP requests and other topics discussed here to really understand Ajax on Rails.
h4. Asynchronous JavaScript + XML
@@ -42,7 +42,7 @@ You are ready to add some AJAX love to your Rails app!
h4. The Quintessential AJAX Rails Helper: link_to_remote
-Let's start with what is probably the most often used helper: +link_to_remote+. It has an interesting feature from the documentation point of view: the options supplied to +link_to_remote+ are shared by all other AJAX helpers, so learning the mechanics and options of +link_to_remote+ is a great help when using other helpers.
+Let's start with what is probably the most often used helper: +link_to_remote+. It has an interesting feature from the documentation point of view: the options supplied to +link_to_remote+ are shared by all other AJAX helpers, so learning the mechanics and options of +link_to_remote+ is a great help when using other helpers.
The signature of +link_to_remote+ function is the same as that of the standard +link_to+ helper:
@@ -62,7 +62,7 @@ link_to_remote "Add to cart",
* The second parameter, the +options+ hash is the most interesting part as it has the AJAX specific stuff:
** *:url* This is the only parameter that is always required to generate the simplest remote link (technically speaking, it is not required, you can pass an empty +options+ hash to +link_to_remote+ - but in this case the URL used for the POST request will be equal to your current URL which is probably not your intention). This URL points to your AJAX action handler. The URL is typically specified by Rails REST view helpers, but you can use the +url_for+ format too.
-** *:update* There are basically two ways of injecting the server response into the page: One is involving RJS and we will discuss it in the next chapter, and the other is specifying a DOM id of the element we would like to update. The above example demonstrates the simplest way of accomplishing this - however, we are in trouble if the server responds with an error message because that will be injected into the page too! However, Rails has a solution for this situation:
+** *:update* Specifying a DOM id of the element we would like to update. The above example demonstrates the simplest way of accomplishing this - however, we are in trouble if the server responds with an error message because that will be injected into the page too! However, Rails has a solution for this situation:
<ruby>
link_to_remote "Add to cart",
@@ -72,7 +72,7 @@ link_to_remote "Add to cart",
If the server returns 200, the output of the above example is equivalent to our first, simple one. However, in case of error, the element with the DOM id +error+ is updated rather than the +cart+ element.
-** *position* By default (i.e. when not specifying this option, like in the examples before) the repsonse is injected into the element with the specified DOM id, replacing the original content of the element (if there was any). You might want to alter this behavior by keeping the original content - the only question is where to place the new content? This can specified by the +position+ parameter, with four possibilities:
+** *position* By default (i.e. when not specifying this option, like in the examples before) the repsonse is injected into the element with the specified DOM id, replacing the original content of the element (if there was any). You might want to alter this behavior by keeping the original content - the only question is where to place the new content? This can specified by the +position+ parameter, with four possibilities:
*** +:before+ Inserts the response text just before the target element. More precisely, it creates a text node from the response and inserts it as the left sibling of the target element.
*** +:after+ Similar behavior to +:before+, but in this case the response is inserted after the target element.
*** +:top+ Inserts the text into the target element, before it's original content. If the target element was empty, this is equivalent with not specifying +:position+ at all.
@@ -178,12 +178,7 @@ h5. +remote_function+
h5. +update_page+
-
-h3. JavaScript the Rails way: RJS
-
-In the last section we sent some AJAX requests to the server, and inserted the HTML response into the page (with the +:update+ option). However, sometimes a more complicated interaction with the page is needed, which you can either achieve with JavaScript... or with RJS! You are sending JavaScript instructions to the server in both cases, but while in the former case you have to write vanilla JavaScript, in the second you can code Rails, and sit back while Rails generates the JavaScript for you - so basically RJS is a Ruby DSL to write JavaScript in your Rails code.
-
-h4. JavaScript without RJS
+h4. Serving JavaScript
First we'll check out how to send JavaScript to the server manually. You are practically never going to need this, but it's interesting to understand what's going on under the hood.
@@ -198,136 +193,6 @@ end
What happens here is that by specifying the Content-Type header variable, we instruct the browser to evaluate the text we are sending over (rather than displaying it as plain text, which is the default behavior).
-h4. Inline RJS
-
-As we said, the purpose of RJS is to write Ruby which is then auto-magically turned into JavaScript by Rails. The above example didn't look too Ruby-esque so let's see how to do it the Rails way:
-
-<ruby>
-def javascript_test
- render :update do |page|
- page.alert "Hello from inline RJS"
- end
-end
-</ruby>
-
-The above code snippet does exactly the same as the one in the previous section - going about it much more elegantly though. You don't need to worry about headers,write ugly JavaScript code into a string etc. When the first parameter to +render+ is +:update+, Rails expects a block with a single parameter (+page+ in our case, which is the traditional naming convention) which is an instance of the JavaScriptGenerator:"http://api.rubyonrails.org/classes/ActionView/Helpers/PrototypeHelper/JavaScriptGenerator/GeneratorMethods.html" object. As it's name suggests, JavaScriptGenerator is responsible for generating JavaScript from your Ruby code. You can execute multiple method calls on the +page+ instance - it's all turned into JavaScript code and sent to the server with the appropriate Content Type, "text/javascript".
-
-h4. RJS Templates
-
-If you don't want to clutter your controllers with view code (especially when your inline RJS is more than a few lines), you can move your RJS code to a template file. RJS templates should go to the +/app/views/+ directory, just as +.html.erb+ or any other view files of the appropriate controller, conventionally named +js.rjs+.
-
-To rewrite the above example, you can leave the body of the action empty, and create a RJS template named +javascript_test.js.rjs+, containing the following line:
-
-<ruby>
-page.alert "Hello from inline RJS"
-</ruby>
-
-h4. RJS Reference
-
-In this section we'll go through the methods RJS offers.
-
-h5. JavaScriptGenerator Methods
-
-h6. DOM Element Manipulation
-
-It is possible to manipulate multiple elements at once through the +page+ JavaScriptGenerator instance. Let's see this in action:
-
-<ruby>
-page.show :div_one, :div_two
-page.hide :div_one
-page.remove :div_one, :div_two, :div_three
-page.toggle :other_div
-</ruby>
-
-The above methods (+show+, +hide+, +remove+, +toggle+) have the same semantics as the Prototype methods of the same name. You can pass an arbitrary number (but at least one) of DOM ids to these calls.
-
-
-h6. Inserting and Replacing Content
-
-You can insert content into an element on the page with the +insert_html+ method:
-
-<ruby>
-page.insert_html :top, :result, '42'
-</ruby>
-
-The first parameter is the position of the new content relative to the element specified by the second parameter, a DOM id.
-
-Position can be one of these four values:
-
-*** +:before+ Inserts the response text just before the target element.
-*** +:after+ The response is inserted after the target element.
-*** +:top+ Inserts the text into the target element, before it's original content.
-*** +:bottom+ The counterpart of +:top+: the response is inserted after the target element's original content.
-
-The third parameter can either be a string, or a hash of options to be passed to ActionView::Base#render - for example:
-
-<ruby>
-page.insert_html :top, :result, :partial => "the_answer"
-</ruby>
-
-You can replace the contents (innerHTML) of an element with the +replace_html+ method. The only difference is that since it's clear where should the new content go, there is no need for a position parameter - so +replace_html+ takes only two arguments,
-the DOM id of the element you wish to modify and a string or a hash of options to be passed to ActionView::Base#render.
-
-h6. Delay
-
-You can delay the execution of a block of code with +delay+:
-
-<ruby>
-page.delay(10) { page.alert('Hey! Just waited 10 seconds') }
-</ruby>
-
-+delay+ takes one parameter (time to wait in seconds) and a block which will be executed after the specified time has passed - whatever else follows a +page.delay+ line is executed immediately, the delay affects only the code in the block.
-
-h6. Reloading and Redirecting
-
-You can reload the page with the +reload+ method:
-
-<ruby>
-page.reload
-</ruby>
-
-When using AJAX, you can't rely on the standard +redirect_to+ controller method - you have to use the +page+'s instance method, also called +redirect_to+:
-
-<ruby>
-page.redirect_to some_url
-</ruby>
-
-h6. Generating Arbitrary JavaScript
-
-Sometimes even the full power of RJS is not enough to accomplish everything, but you still don't want to drop to pure JavaScript. A nice golden mean is offered by the combination of +<<+, +assign+ and +call+ methods:
-
-<ruby>
- page << "alert('1+1 equals 3')"
-</ruby>
-
-So +<<+ is used to execute an arbitrary JavaScript statement, passed as string to the method. The above code is equivalent to:
-
-<ruby>
- page.assign :result, 3
- page.call :alert, '1+1 equals ' + result
-</ruby>
-
-+assign+ simply assigns a value to a variable. +call+ is similar to +<<+ with a slightly different syntax: the first parameter is the name of the function to call, followed by the list of parameters passed to the function.
-
-h6. Class Proxies
-
-h5. Element Proxies
-
-h5. Collection Proxies
-
-h5. RJS Helpers
-
-
-
-h3. I Want my Yellow Thingy: Quick overview of Script.aculo.us
-
-h4. Introduction
-
-h4. Visual Effects
-
-h4. Drag and Drop
-
-
h3. Testing JavaScript
diff --git a/railties/guides/source/api_documentation_guidelines.textile b/railties/guides/source/api_documentation_guidelines.textile
index 7433507866..e22ffa4c04 100644
--- a/railties/guides/source/api_documentation_guidelines.textile
+++ b/railties/guides/source/api_documentation_guidelines.textile
@@ -29,7 +29,7 @@ Documentation has to be concise but comprehensive. Explore and document edge cas
The proper names of Rails components have a space in between the words, like "Active Support". +ActiveRecord+ is a Ruby module, whereas Active Record is an ORM. All Rails documentation should consistently refer to Rails components by their proper name, and if in your next blog post or presentation you remember this tidbit and take it into account that'd be phenomenal.
-Spell names correctly: Arel, Test::Unit, RSpec, HTML, MySQL, JavaScript, ERb. When in doubt, please have a look at some authoritative source like their official documentation.
+Spell names correctly: Arel, Test::Unit, RSpec, HTML, MySQL, JavaScript, ERB. When in doubt, please have a look at some authoritative source like their official documentation.
Use the article "an" for "SQL", as in "an SQL statement". Also "an SQLite database".
diff --git a/railties/guides/source/association_basics.textile b/railties/guides/source/association_basics.textile
index e5b8c73c43..94dce1b97b 100644
--- a/railties/guides/source/association_basics.textile
+++ b/railties/guides/source/association_basics.textile
@@ -229,7 +229,7 @@ The corresponding migration might look like this:
<ruby>
class CreateSuppliers < ActiveRecord::Migration
- def self.up
+ def change
create_table :suppliers do |t|
t.string :name
t.timestamps
@@ -241,11 +241,6 @@ class CreateSuppliers < ActiveRecord::Migration
t.timestamps
end
end
-
- def self.down
- drop_table :accounts
- drop_table :suppliers
- end
end
</ruby>
@@ -314,7 +309,7 @@ If you have an instance of the +Picture+ model, you can get to its parent via +@
<ruby>
class CreatePictures < ActiveRecord::Migration
- def self.up
+ def change
create_table :pictures do |t|
t.string :name
t.integer :imageable_id
@@ -322,10 +317,6 @@ class CreatePictures < ActiveRecord::Migration
t.timestamps
end
end
-
- def self.down
- drop_table :pictures
- end
end
</ruby>
@@ -333,17 +324,13 @@ This migration can be simplified by using the +t.references+ form:
<ruby>
class CreatePictures < ActiveRecord::Migration
- def self.up
+ def change
create_table :pictures do |t|
t.string :name
t.references :imageable, :polymorphic => true
t.timestamps
end
end
-
- def self.down
- drop_table :pictures
- end
end
</ruby>
@@ -413,17 +400,13 @@ This declaration needs to be backed up by the proper foreign key declaration on
<ruby>
class CreateOrders < ActiveRecord::Migration
- def self.up
+ def change
create_table :orders do |t|
t.datetime :order_date
t.string :order_number
t.integer :customer_id
end
end
-
- def self.down
- drop_table :orders
- end
end
</ruby>
@@ -451,16 +434,12 @@ These need to be backed up by a migration to create the +assemblies_parts+ table
<ruby>
class CreateAssemblyPartJoinTable < ActiveRecord::Migration
- def self.up
+ def change
create_table :assemblies_parts, :id => false do |t|
t.integer :assembly_id
t.integer :part_id
end
end
-
- def self.down
- drop_table :assemblies_parts
- end
end
</ruby>
diff --git a/railties/guides/source/caching_with_rails.textile b/railties/guides/source/caching_with_rails.textile
index 297ba2d661..799339e674 100644
--- a/railties/guides/source/caching_with_rails.textile
+++ b/railties/guides/source/caching_with_rails.textile
@@ -25,7 +25,7 @@ h4. Page Caching
Page caching is a Rails mechanism which allows the request for a generated page to be fulfilled by the webserver (i.e. apache or nginx), without ever having to go through the Rails stack at all. Obviously, this is super-fast. Unfortunately, it can't be applied to every situation (such as pages that need authentication) and since the webserver is literally just serving a file from the filesystem, cache expiration is an issue that needs to be dealt with.
-So, how do you enable this super-fast cache behavior? Simple, let's say you have a controller called +ProductsController+ and an +index+ action that lists all the products
+So, how do you enable this super-fast cache behavior? Simple, let's say you have a controller called +ProductsController+ and an +index+ action that lists all the products
<ruby>
class ProductsController < ActionController
@@ -152,7 +152,7 @@ expire_fragment('all_available_products')
h4. Sweepers
-Cache sweeping is a mechanism which allows you to get around having a ton of +expire_{page,action,fragment}+ calls in your code. It does this by moving all the work required to expire cached content into an +ActionController::Caching::Sweeper+ subclass. This class is an observer and looks for changes to an object via callbacks, and when a change occurs it expires the caches associated with that object in an around or after filter.
+Cache sweeping is a mechanism which allows you to get around having a ton of +expire_{page,action,fragment}+ calls in your code. It does this by moving all the work required to expire cached content into an +ActionController::Caching::Sweeper+ subclass. This class is an observer and looks for changes to an object via callbacks, and when a change occurs it expires the caches associated with that object in an around or after filter.
Continuing with our Product controller example, we could rewrite it with a sweeper like this:
@@ -230,9 +230,9 @@ class ProductsController < ActionController
end
</ruby>
-The second time the same query is run against the database, it's not actually going to hit the database. The first time the result is returned from the query it is stored in the query cache (in memory) and the second time it's pulled from memory.
+The second time the same query is run against the database, it's not actually going to hit the database. The first time the result is returned from the query it is stored in the query cache (in memory) and the second time it's pulled from memory.
-However, it's important to note that query caches are created at the start of an action and destroyed at the end of that action and thus persist only for the duration of the action. If you'd like to store query results in a more persistent fashion, you can in Rails by using low level caching.
+However, it's important to note that query caches are created at the start of an action and destroyed at the end of that action and thus persist only for the duration of the action. If you'd like to store query results in a more persistent fashion, you can in Rails by using low level caching.
h3. Cache Stores
@@ -322,7 +322,7 @@ You can use Hashes and Arrays of values as cache keys.
<ruby>
# This is a legal cache key
-Rails.cache.read(:site => "mysite", :owners => [owner_1, owner2])
+Rails.cache.read(:site => "mysite", :owners => [owner_1, owner_2])
</ruby>
The keys you use on +Rails.cache+ will not be the same as those actually used with the storage engine. They may be modified with a namespace or altered to fit technology backend constraints. This means, for instance, that you can't save values with +Rails.cache+ and then try to pull them out with the +memcache-client+ gem. However, you also don't need to worry about exceeding the memcached size limit or violating syntax rules.
@@ -352,7 +352,7 @@ class ProductsController < ApplicationController
# If the request is fresh (i.e. it's not modified) then you don't need to do
# anything. The default render checks for this using the parameters
# used in the previous call to stale? and will automatically send a
- # :not_modified. So that's it, you're done.
+ # :not_modified. So that's it, you're done.
end
</ruby>
diff --git a/railties/guides/source/command_line.textile b/railties/guides/source/command_line.textile
index 581fece1ab..ad36c6532e 100644
--- a/railties/guides/source/command_line.textile
+++ b/railties/guides/source/command_line.textile
@@ -8,10 +8,10 @@ Rails comes with every command line tool you'll need to
* Mess with objects through an interactive shell
* Profile and benchmark your new creation
-NOTE: This tutorial assumes you have basic Rails knowledge from reading the "Getting Started with Rails Guide":getting_started.html.
-
endprologue.
+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.0. Some of the code shown here will not work in earlier versions of Rails.
h3. Command Line Basics
@@ -144,10 +144,13 @@ $ rails generate controller Greetings hello
create app/helpers/greetings_helper.rb
invoke test_unit
create test/unit/helpers/greetings_helper_test.rb
+ invoke assets
+ create app/assets/javascripts/greetings.js
+ create app/assets/stylesheets/greetings.css
</shell>
-What all did this generate? It made sure a bunch of directories were in our application, and created a controller file, a functional test file, a helper for the view, and a view file.
+What all did this generate? It made sure a bunch of directories were in our application, and created a controller file, a view file, a functional test file, a helper for the view, a javascript file and a stylesheet file.
Check out the controller and modify it a little (in +app/controllers/greetings_controller.rb+):
@@ -215,13 +218,13 @@ $ rails generate scaffold HighScore game:string score:integer
create app/views/layouts/
exists test/functional/
create test/unit/
- create public/stylesheets/
+ create app/assets/stylesheets/
create app/views/high_scores/index.html.erb
create app/views/high_scores/show.html.erb
create app/views/high_scores/new.html.erb
create app/views/high_scores/edit.html.erb
create app/views/layouts/high_scores.html.erb
- create public/stylesheets/scaffold.css
+ create app/assets/stylesheets/scaffold.css.scss
create app/controllers/high_scores_controller.rb
create test/functional/high_scores_controller_test.rb
create app/helpers/high_scores_helper.rb
@@ -484,7 +487,7 @@ end
We take whatever args are supplied, save them to an instance variable, and literally copying from the Rails source, implement a +manifest+ method, which calls +record+ with a block, and we:
* Check there's a *public* directory. You bet there is.
-* Run the ERb template called "tutorial.erb".
+* Run the ERB template called "tutorial.erb".
* Save it into "Rails.root/public/tutorial.txt".
* Pass in the arguments we saved through the +:assigns+ parameter.
diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile
index 298335d484..d7069b31fc 100644
--- a/railties/guides/source/configuring.textile
+++ b/railties/guides/source/configuring.textile
@@ -149,7 +149,7 @@ h4. Configuring Middleware
Every Rails application comes with a standard set of middleware which it uses in this order in the development environment:
-* +Rack::SSL+ Will force every requests to be under HTTPS protocol. Will be available if +config.force_ssl+ is set to _true_.
+* +Rack::SSL+ Will force every request to be under HTTPS protocol. Will be available if +config.force_ssl+ is set to _true_.
* +ActionDispatch::Static+ is used to serve static assets. Disabled if +config.serve_static_assets+ is _true_.
* +Rack::Lock+ Will wrap the app in mutex so it can only be called by a single thread at a time. Only enabled if +config.action_controller.allow_concurrency+ is set to _false_, which it is by default.
* +ActiveSupport::Cache::Strategy::LocalCache+ Serves as a basic memory backed cache. This cache is not thread safe and is intended only for serving as a temporary memory cache for a single thread.
@@ -229,6 +229,8 @@ h4. Configuring Active Record
* +config.active_record.lock_optimistically+ controls whether ActiveRecord will use optimistic locking. By default this is +true+.
+* +config.active_record.whitelist_attributes+ will create an empty whitelist of attributes available for mass-assignment security for all models in your app.
+
The MySQL adapter adds one additional configuration option:
* +ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans+ controls whether ActiveRecord will consider all +tinyint(1)+ columns in a MySQL database to be booleans. By default this is +true+.
@@ -291,8 +293,6 @@ h4. Configuring Action View
There are only a few configuration options for Action View, starting with four on +ActionView::Base+:
-* +config.action_view.debug_rjs+ specifies whether RJS responses should be wrapped in a try/catch block that alerts the caught exception (and then re-raises it). The default is +false+.
-
* +config.action_view.field_error_proc+ provides an HTML generator for displaying errors that come from Active Record. The default is <tt>Proc.new{ |html_tag, instance| %Q(%&lt;div class=&quot;field_with_errors&quot;&gt;#{html_tag}&lt;/div&gt;).html_safe }</tt>
* +config.action_view.default_form_builder+ tells Rails which form builder to use by default. The default is +ActionView::Helpers::FormBuilder+.
diff --git a/railties/guides/source/contributing_to_ruby_on_rails.textile b/railties/guides/source/contributing_to_ruby_on_rails.textile
index 1fcc4fd7e3..cb09b180a2 100644
--- a/railties/guides/source/contributing_to_ruby_on_rails.textile
+++ b/railties/guides/source/contributing_to_ruby_on_rails.textile
@@ -2,7 +2,7 @@ h2. Contributing to Ruby on Rails
This guide covers ways in which _you_ can become a part of the ongoing development of Ruby on Rails. After reading it, you should be familiar with:
-* Using Lighthouse to report issues
+* Using GitHub to report issues
* Cloning master and running the test suite
* Helping to resolve existing issues
* Contributing to the Ruby on Rails documentation
@@ -14,29 +14,25 @@ endprologue.
h3. Reporting an Issue
-Ruby on Rails uses a "Lighthouse project":http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/ 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) Lighthouse account in order to comment on issues or to upload patches.
+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 either submit an issue, comment on them or 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.
h4. Creating a Bug Report
-If you've found a problem in Ruby on Rails which is not a security risk do a search in Lighthouse in case it was already reported. If you find no ticket addressing it you can "add a new one":http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/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 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 ticket needs a title and descriptive text. But that's only a minimum. You should include as much relevant information as possible. You need to at least 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.
+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 to at least 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.
-You shouldn't assign the bug to a particular core developer unless you know for sure which developer will be handling that issue. The core team periodically reviews issues and assigns developers and milestones to them.
-
-You should set tags for your issue. Use the "bug" tag for a bug report, and add the "patch" tag if you are attaching a patch. Try to find some relevant tags from the existing tag list (which will appear as soon as you start typing in the "Choose some tags" textbox), rather than creating new tags.
-
-Then don't get your hopes up. Unless you have a "Code Red, Mission Critical, The World is Coming to an End" kind of bug, you're creating this ticket in the hope that others with the same problem will be able to collaborate with you on solving it. Do not expect that the ticket automatically will see any activity or that others will jump to fix it. Creating a ticket like this is mostly to help yourself start on the path of fixing the problem and for others to confirm it with a "I'm having this problem too" comment.
+Then don't get your hopes up. Unless you have a "Code Red, Mission Critical, The World is Coming to an End" kind of bug, you're creating this issue report in the hope that others with the same problem will be able to collaborate with you on solving it. Do not expect that the issue report will automatically see any activity or that others will jump to fix it. Creating a issue like this is mostly to help yourself start on the path of fixing the problem and for others to confirm it with a "I'm having this problem too" comment.
h4. Special Treatment for Security Issues
-WARNING: Please do not report security vulnerabilities on public Lighthouse tickets. 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.
h4. What About Feature Requests?
-Please don't put "feature request" tickets into Lighthouse. 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 Lighthouse with no code, you can expect it to be marked "invalid" as soon as it's reviewed.
+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.
h3. Running the Test Suite
@@ -48,7 +44,7 @@ Ruby on Rails uses git for source code control. The "git homepage":http://git-sc
* "Everyday Git":http://www.kernel.org/pub/software/scm/git/docs/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":https://github.com/guides/home offers links to a variety of git resources.
+* "GitHub":http://help.github.com offers links to a variety of git resources.
* "Pro Git":http://progit.org/book/ is an entire book about git with a Creative Commons license.
h4. Clone the Ruby on Rails Repository
@@ -216,11 +212,11 @@ TIP: You may want to "put your git branch name in your shell prompt":http://qugs
h3. 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 "open tickets":https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets?q=state%3Aopen list in Lighthouse, 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?sort=created&direction=desc&state=open&page=1 list in GitHub Issues, you'll find lots of issues already requiring attention. What can you do for these? Quite a bit, actually:
h4. Verifying Bug Reports
-For starters, it helps to just verify bug reports. Can you reproduce the reported issue on your own computer? If so, you can add a comment to the ticket saying that you're seeing the same thing.
+For starters, it helps to just verify bug reports. Can you reproduce the reported issue on your own computer? If so, you can add a comment to the issue saying that you're seeing the same thing.
If something is very vague, can you help squish it down into something specific? Maybe you can provide additional information to help reproduce a bug, or eliminate needless steps that aren't required to help demonstrate the problem.
@@ -230,38 +226,39 @@ Anything you can do to make bug reports more succinct or easier to reproduce is
h4. Testing Patches
-You can also help out by examining patches that have been submitted to Ruby on Rails via Lighthouse. To apply someone's changes you need to first create a dedicated branch:
+You can also help out by examining pull requests that have been submitted to Ruby on Rails via GitHub. To apply someone's changes you need to first create a dedicated branch:
<shell>
$ git checkout -b testing_branch
</shell>
-Then you can apply their patch:
+Then you can use their remote branch to update your codebase. For example, let's say the GitHub user JohnSmith has forked and pushed to the master branch located at https://github.com/JohnSmith/rails.
<shell>
-$ git am their-patch-file.diff
+$ git remote add JohnSmith git://github.com/JohnSmith/rails.git
+$ git pull JohnSmith master
</shell>
-After applying a patch, test it out! Here are some things to think about:
+After applying their branch, test it out! Here are some things to think about:
-* Does the patch actually work?
+* Does the change actually work?
* Are you happy with the tests? Can you follow what they're testing? Are there any tests missing?
* Does it have proper documentation coverage? Should documentation elsewhere be updated?
* Do you like the implementation? Can you think of a nicer or faster way to implement a part of their change?
-Once you're happy that the patch contains a good change, comment on the Lighthouse ticket indicating your approval. Your comment should indicate that you like the change and what you like about it. Something like:
+Once you're happy that the pull request contains a good change, comment on the GitHub issue indicating your approval. Your comment should indicate that you like the change and what you like about it. Something like:
<blockquote>
I like the way you've restructured that code in generate_finder_sql, much nicer. The tests look good too.
</blockquote>
-If your comment simply says "+1", then odds are that other reviewers aren't going to take it too seriously. Show that you took the time to review the patch. Once three people have approved it, add the "verified" tag. This will bring it to the attention of a core team member who will review the changes looking for the same kinds of things.
+If your comment simply says "+1", then odds are that other reviewers aren't going to take it too seriously. Show that you took the time to review the pull request.
h3. Contributing to the Rails Documentation
Ruby on Rails has two main sets of documentation: The guides help you to learn Ruby on Rails, and the API is a reference.
-You can create a ticket in Lighthouse to fix or expand documentation. However, if you're confident about your changes you can push them yourself directly via "docrails":https://github.com/lifo/docrails/tree/master. docrails is a branch with an *open commit policy* and public write access. Commits to docrails are still reviewed, but that happens after they are pushed. docrails is merged with master regularly, so you are effectively editing the Ruby on Rails documentation.
+You can create an issue in GitHub issues to fix or expand documentation. However, if you're confident about your changes you can push them yourself directly via "docrails":https://github.com/lifo/docrails/tree/master. docrails is a branch with an *open commit policy* and public write access. Commits to docrails are still reviewed, but that happens after they are pushed. docrails is merged with master regularly, so you are effectively editing the Ruby on Rails documentation.
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.
@@ -319,7 +316,7 @@ h4. Commit Your Changes
When you're happy with the code on your computer, you need to commit the changes to git:
<shell>
-$ git commit -a -m "Here is a commit message"
+$ git commit -a -m "Here is a commit message on what I changed in this commit"
</shell>
h4. Update master
@@ -340,34 +337,29 @@ $ git rebase master
No conflicts? Tests still pass? Change still seems reasonable to you? Then move on.
-h4. Create a Patch
-
-Now you can create a patch file to share with other developers (and with the core team). Still in your branch, run
-
-<shell>
-$ git commit -a
-$ git format-patch master --stdout > my_new_patch.diff
-</shell>
+h4. Fork
-Open the diff file in your text editor of choice to sanity check the results, and make sure that no unintended changes crept in.
+Navigate to the Rails "GitHub repository":https://github.com/rails/rails and press "Fork" in the upper right hand corner.
-You can also perform an extra check by applying the patch to a different dedicated branch:
+Add the new remote to your local repository on your local machine:
<shell>
-$ git checkout -b testing_branch
-$ git apply --check my_new_patch.diff
+$ git remote add mine https://&lt;your user name&gt;@github.com/&lt;your user name&gt;/rails.git
</shell>
-Please make sure the patch does not introduce whitespace errors:
+Push to your remote:
<shell>
-$ git apply --whitespace=error-all mynew_patch.diff
+$ git push mine master
</shell>
+h4. Issue a Pull Request
-h4. Create a Lighthouse Ticket
+Navigate to the Rails repository you just pushed to (e.g. https://github.com/&lt;your user name&gt;/rails) and press "Pull Request" in the upper right hand corner.
+
+Ensure the changesets you introduced are included in the "Commits" tab and that the "Files Changed" incorporate all of your changes.
-Now create a ticket with your patch. Go to the "new ticket":http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/new page at Lighthouse. Fill in a reasonable title and description, remember to attach your patch file, and tag the ticket with the ‘patch’ tag and whatever other subject area tags make sense.
+Fill in some details about your potential patch including a meaningful title. When finished, press "Send pull request." Rails Core will be notified about your submission.
h4. Get Some Feedback
@@ -385,8 +377,9 @@ All contributions, either via master or docrails, get credit in "Rails Contribut
h3. Changelog
+* April 29, 2011: Reflect GitHub Issues and Pull Request workflow by "Dan Pickett":http://www.enlightsolutions.com
+* April 14, 2011: Modified Contributing to the Rails Code section to add '[#ticket_number state:commited]' on patches commit messages by "Sebastian Martinez":http://wyeworks.com
* December 28, 2010: Complete revision by "Xavier Noria":credits.html#fxn
* April 6, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com
* August 1, 2009: Updates/amplifications by "Mike Gunderloy":credits.html#mgunderloy
* March 2, 2009: Initial draft by "Mike Gunderloy":credits.html#mgunderloy
-
diff --git a/railties/guides/source/debugging_rails_applications.textile b/railties/guides/source/debugging_rails_applications.textile
index 045b8823ca..6f028805d6 100644
--- a/railties/guides/source/debugging_rails_applications.textile
+++ b/railties/guides/source/debugging_rails_applications.textile
@@ -96,26 +96,6 @@ Will be rendered as follows:
Title: Rails debugging guide
</pre>
-h4. Debugging RJS
-
-Rails has optional built-in support to debug RJS. When enabled, responses are wrapped in a try/catch block that displays the caught exception using +alert()+, and then re-raises it.
-
-The flag to enable RJS debugging in your configuration files is +config.action_view.debug_rjs+:
-
-<ruby>
-config.action_view.debug_rjs = true
-</ruby>
-
-or at any time setting +ActionView::Base.debug_rjs+:
-
-<ruby>
-ActionView::Base.debug_rjs = true
-</ruby>
-
-It is enabled by default in development mode, and disabled in the rest.
-
-TIP: For more information on debugging JavaScript, refer to "Firebug":http://getfirebug.com/, the popular debugger for Firefox.
-
h3. The Logger
It can also be useful to save information to log files at runtime. Rails maintains a separate log file for each runtime environment.
@@ -299,14 +279,14 @@ This command shows you where you are in the code by printing 10 lines centered a
[1, 10] in /PathToProject/posts_controller.rb
1 class PostsController < ApplicationController
2 # GET /posts
- 3 # GET /posts.xml
+ 3 # GET /posts.json
4 def index
5 debugger
=> 6 @posts = Post.all
7
8 respond_to do |format|
9 format.html # index.html.erb
- 10 format.xml { render :xml => @posts }
+ 10 format.json { render :json => @posts }
</shell>
If you repeat the +list+ command, this time using just +l+, the next ten lines of the file will be printed out.
@@ -318,7 +298,7 @@ If you repeat the +list+ command, this time using just +l+, the next ten lines o
12 end
13
14 # GET /posts/1
- 15 # GET /posts/1.xml
+ 15 # GET /posts/1.json
16 def show
17 @post = Post.find(params[:id])
18
@@ -328,6 +308,41 @@ If you repeat the +list+ command, this time using just +l+, the next ten lines o
And so on until the end of the current file. When the end of file is reached, the +list+ command will start again from the beginning of the file and continue again up to the end, treating the file as a circular buffer.
+On the other hand, to see the previous ten lines you should type +list-+ (or +l-+)
+
+<shell>
+(rdb:7) l-
+[1, 10] in /PathToProject/posts_controller.rb
+ 1 class PostsController < ApplicationController
+ 2 # GET /posts
+ 3 # GET /posts.json
+ 4 def index
+ 5 debugger
+ 6 @posts = Post.all
+ 7
+ 8 respond_to do |format|
+ 9 format.html # index.html.erb
+ 10 format.json { render :json => @posts }
+</shell>
+
+This way you can move inside the file, being able to see the code above and over the line you added the +debugger+.
+Finally, to see where you are in the code again you can type +list=+
+
+<shell>
+(rdb:7) list=
+[1, 10] in /PathToProject/posts_controller.rb
+ 1 class PostsController < ApplicationController
+ 2 # GET /posts
+ 3 # GET /posts.json
+ 4 def index
+ 5 debugger
+=> 6 @posts = Post.all
+ 7
+ 8 respond_to do |format|
+ 9 format.html # index.html.erb
+ 10 format.json { render :json => @posts }
+</shell>
+
h4. The Context
When you start debugging your application, you will be placed in different contexts as you go through the different parts of the stack.
diff --git a/railties/guides/source/form_helpers.textile b/railties/guides/source/form_helpers.textile
index 1f21c27ae6..a63245acec 100644
--- a/railties/guides/source/form_helpers.textile
+++ b/railties/guides/source/form_helpers.textile
@@ -258,7 +258,7 @@ The name passed to +form_for+ controls the key used in +params+ to access the fo
The helper methods called on the form builder are identical to the model object helpers except that it is not necessary to specify which object is being edited since this is already managed by the form builder.
-You can create a similar binding without actually creating +&lt;form&gt;+ tags with the +fields_for+ helper. This is useful for editing additional model objects with the same form. For example if you had a Person model with an associated ContactDetail model you could create a form for creating both like so:
+You can create a similar binding without actually creating +&lt;form&gt;+ tags with the +fields_for+ helper. This is useful for editing additional model objects with the same form. For example if you had a Person model with an associated ContactDetail model you could create a form for creating both like so:
<erb>
<%= form_for @person, :url => { :action => "create" } do |person_form| %>
@@ -438,7 +438,7 @@ As with other helpers, if you were to use the +select+ helper on a form builder
<%= f.select(:city_id, ...) %>
</erb>
-WARNING: If you are using +select+ (or similar helpers such as +collection_select+, +select_tag+) to set a +belongs_to+ association you must pass the name of the foreign key (in the example above +city_id+), not the name of association itself. If you specify +city+ instead of +city_id+ Active Record will raise an error along the lines of <tt> ActiveRecord::AssociationTypeMismatch: City(#17815740) expected, got String(#1138750) </tt> when you pass the +params+ hash to +Person.new+ or +update_attributes+. Another way of looking at this is that form helpers only edit attributes. You should also be aware of the potential security ramifications of allowing users to edit foreign keys directly. You may wish to consider the use of +attr_protected+ and +attr_accessible+. For further details on this, see the "Ruby On Rails Security Guide":security.html#_mass_assignment.
+WARNING: If you are using +select+ (or similar helpers such as +collection_select+, +select_tag+) to set a +belongs_to+ association you must pass the name of the foreign key (in the example above +city_id+), not the name of association itself. If you specify +city+ instead of +city_id+ Active Record will raise an error along the lines of <tt> ActiveRecord::AssociationTypeMismatch: City(#17815740) expected, got String(#1138750) </tt> when you pass the +params+ hash to +Person.new+ or +update_attributes+. Another way of looking at this is that form helpers only edit attributes. You should also be aware of the potential security ramifications of allowing users to edit foreign keys directly. You may wish to consider the use of +attr_protected+ and +attr_accessible+. For further details on this, see the "Ruby On Rails Security Guide":security.html#_mass_assignment.
h4. Option Tags from a Collection of Arbitrary Objects
@@ -513,7 +513,7 @@ The +:prefix+ option is the key used to retrieve the hash of date components fro
h4(#select-model-object-helpers). Model Object Helpers
+select_date+ does not work well with forms that update or create Active Record objects as Active Record expects each element of the +params+ hash to correspond to one attribute.
-The model object helpers for dates and times submit parameters with special names, when Active Record sees parameters with such names it knows they must be combined with the other parameters and given to a constructor appropriate to the column type. For example:
+The model object helpers for dates and times submit parameters with special names, when Active Record sees parameters with such names it knows they must be combined with the other parameters and given to a constructor appropriate to the column type. For example:
<erb>
<%= date_select :person, :birth_date %>
diff --git a/railties/guides/source/generators.textile b/railties/guides/source/generators.textile
index d32ba48003..ac709968d9 100644
--- a/railties/guides/source/generators.textile
+++ b/railties/guides/source/generators.textile
@@ -190,7 +190,7 @@ $ rails generate scaffold User name:string
invoke test_unit
create test/unit/helpers/users_helper_test.rb
invoke stylesheets
- create public/stylesheets/scaffold.css
+ create app/assets/stylesheets/scaffold.css
</shell>
Looking at this output, it's easy to understand how generators work in Rails 3.0 and above. The scaffold generator doesn't actually generate anything, it just invokes others to do the work. This allows us to add/replace/remove any of those invocations. For instance, the scaffold generator invokes the scaffold_controller generator, which invokes erb, test_unit and helper generators. Since each generator has a single responsibility, they are easy to reuse, avoiding code duplication.
@@ -383,7 +383,7 @@ if yes?("Would you like to install Devise?")
end
</ruby>
-In the above template we specify that the application relies on the +rspec-rails+ and +cucumber-rails+ gem so these two will be added to the +test+ group in the +Gemfile+. Then we pose a question to the user about whether or not they would like to install Devise. If the user replies "y" or "yes" to this question, then the template will add Devise to the +Gemfile+ outside of any group and then runs the +devise:install+ generator. This template then takes the users input and runs the +devise+ generator, with the user's answer from the last question being passed to this generator.
+In the above template we specify that the application relies on the +rspec-rails+ and +cucumber-rails+ gem so these two will be added to the +test+ group in the +Gemfile+. Then we pose a question to the user about whether or not they would like to install Devise. If the user replies "y" or "yes" to this question, then the template will add Devise to the +Gemfile+ outside of any group and then runs the +devise:install+ generator. This template then takes the users input and runs the +devise+ generator, with the user's answer from the last question being passed to this generator.
Imagine that this template was in a file called +template.rb+. We can use it to modify the outcome of the +rails new+ command by using the +-m+ option and passing in the filename:
diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile
index 0661549644..a826a33120 100644
--- a/railties/guides/source/getting_started.textile
+++ b/railties/guides/source/getting_started.textile
@@ -22,7 +22,7 @@ TIP: Note that Ruby 1.8.7 p248 and p249 have marshaling bugs that crash Rails 3.
* The "RubyGems":http://rubyforge.org/frs/?group_id=126 packaging system
* 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:
+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/
@@ -78,7 +78,7 @@ Rails ships as many individual components.
h5. Action Pack
-Action Pack is a single gem that contains Action Controller, Action View and Action Dispatch. The "VC" part of "MVC".
+Action Pack is a single gem that contains Action Controller, Action View and Action Dispatch. The "VC" part of "MVC".
h5. Action Controller
@@ -98,7 +98,7 @@ Action Mailer is a framework for building e-mail services. You can use Action Ma
h5. Active Model
-Active Model provides a defined interface between the Action Pack gem services and Object Relationship Mapping gems such as Active Record. Active Model allows Rails to utilize other ORM frameworks in place of Active Record if your application needs this.
+Active Model provides a defined interface between the Action Pack gem services and Object Relationship Mapping gems such as Active Record. Active Model allows Rails to utilize other ORM frameworks in place of Active Record if your application needs this.
h5. Active Record
@@ -153,7 +153,7 @@ TIP. If you're working on Windows, you can quickly install Ruby and Rails with "
h4. Creating the Blog Application
-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. If you need to see the completed code, you can download it from "Getting Started Code":https://github.com/mikel/getting-started-code.
+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. If you need to see the completed code, you can download it from "Getting Started Code":https://github.com/mikel/getting-started-code.
To begin, open a terminal, navigate to a folder where you have rights to create files, and type:
@@ -184,7 +184,7 @@ In any case, Rails will create a folder in your working directory called <tt>blo
|doc/|In-depth documentation for your application.|
|lib/|Extended modules for your application (not covered in this guide).|
|log/|Application log files.|
-|public/|The only folder seen to the world as-is. This is where your images, JavaScript files, stylesheets (CSS), and other static files go.|
+|public/|The only folder seen to the world as-is. This is where your images, JavaScript files, stylesheets (CSS), and other static files go.|
|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|
|tmp/|Temporary files|
@@ -290,7 +290,7 @@ This will fire up an instance of the WEBrick web server by default (Rails can al
TIP: To stop the web server, hit Ctrl+C in the terminal window where it's running. In development mode, Rails does not generally require you to stop the server; changes you make in files will be automatically picked up by the server.
-The "Welcome Aboard" page is the _smoke test_ for a new Rails application: it makes sure that you have your software configured correctly enough to serve a page. You can also click on the _About your application’s environment_ link to see a summary of your Application's environment.
+The "Welcome Aboard" page is the _smoke test_ for a new Rails application: it makes sure that you have your software configured correctly enough to serve a page. You can also click on the _About your application’s environment_ link to see a summary of your Application's environment.
h4. Say "Hello", Rails
@@ -310,7 +310,7 @@ Rails will create several files for you, including +app/views/home/index.html.er
h4. 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, instead of the "Welcome Aboard" smoke test.
+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, instead of the "Welcome Aboard" smoke test.
The first step to doing this is to delete the default page from your application:
@@ -368,7 +368,7 @@ The scaffold generator will build 15 files in your application, along with some
|test/functional/posts_controller_test.rb |Functional testing harness for the posts controller|
|test/unit/helpers/posts_helper_test.rb |Unit testing harness for the posts helper|
|config/routes.rb |Edited to include routing information for posts|
-|public/stylesheets/scaffold.css |Cascading style sheet to make the scaffolded views look better|
+|app/assets/stylesheets/scaffold.css.scss |Cascading style sheet to make the scaffolded views look better|
h4. Running a Migration
@@ -378,7 +378,7 @@ If you look in the +db/migrate/20100207214725_create_posts.rb+ file (remember, y
<ruby>
class CreatePosts < ActiveRecord::Migration
- def self.up
+ def change
create_table :posts do |t|
t.string :name
t.string :title
@@ -387,14 +387,10 @@ class CreatePosts < ActiveRecord::Migration
t.timestamps
end
end
-
- def self.down
- drop_table :posts
- end
end
</ruby>
-The above migration creates two methods, +up+, called when you run this migration into the database, and +down+ in case you need to reverse the changes made by this migration at a later date. The +up+ command in this case creates a +posts+ table with two string columns and a text column. It also creates two timestamp fields to track record creation and updating. More information about Rails migrations can be found in the "Rails Database Migrations":migrations.html guide.
+The above migration creates a method name +change+ which will be called when you run this migration. The action defined in that method is also reversible, which means Rails knows how to reverse the change made by this migration, in case you want to reverse it at later date. By default, when you run this migration it will creates a +posts+ table with two string columns and a text column. It also creates two timestamp fields to track record creation and updating. More information about Rails migrations can be found in the "Rails Database Migrations":migrations.html guide.
At this point, you can use a rake command to run the migration:
@@ -501,8 +497,8 @@ def index
@posts = Post.all
respond_to do |format|
- format.html # index.html.erb
- format.xml { render :xml => @posts }
+ format.html # index.html.erb
+ format.json { render :json => @posts }
end
end
</ruby>
@@ -511,7 +507,7 @@ end
TIP: For more information on finding records with Active Record, see "Active Record Query Interface":active_record_querying.html.
-The +respond_to+ block handles both HTML and XML calls to this action. If you browse to "http://localhost:3000/posts.xml":http://localhost:3000/posts.xml, you'll see all of the posts in XML format. The HTML format looks for a view in +app/views/posts/+ with a name that corresponds to the action name. Rails makes all of the instance variables from the action available to the view. Here's +app/views/posts/index.html.erb+:
+The +respond_to+ block handles both HTML and JSON calls to this action. If you browse to "http://localhost:3000/posts.json":http://localhost:3000/posts.json, you'll see a JSON containing all of the posts. The HTML format looks for a view in +app/views/posts/+ with a name that corresponds to the action name. Rails makes all of the instance variables from the action available to the view. Here's +app/views/posts/index.html.erb+:
<erb>
<h1>Listing posts</h1>
@@ -548,7 +544,7 @@ This view iterates over the contents of the +@posts+ array to display content an
* +link_to+ builds a hyperlink to a particular destination
* +edit_post_path+ and +new_post_path+ are helpers that Rails provides as part of RESTful routing. You'll see a variety of these helpers for the different actions that the controller includes.
-NOTE. In previous versions of Rails, you had to use +&lt;%=h post.name %&gt;+ so that any HTML would be escaped before being inserted into the page. In Rails 3.0, this is now the default. To get unescaped HTML, you now use +&lt;%= raw post.name %&gt;+.
+NOTE. In previous versions of Rails, you had to use +&lt;%=h post.name %&gt;+ so that any HTML would be escaped before being inserted into the page. In Rails 3.0, this is now the default. To get unescaped HTML, you now use +&lt;%= raw post.name %&gt;+.
TIP: For more details on the rendering process, see "Layouts and Rendering in Rails":layouts_and_rendering.html.
@@ -584,8 +580,8 @@ def new
@post = Post.new
respond_to do |format|
- format.html # new.html.erb
- format.xml { render :xml => @post }
+ format.html # new.html.erb
+ format.json { render :json => @post }
end
end
</ruby>
@@ -600,7 +596,7 @@ The +new.html.erb+ view displays this empty Post to the user:
<%= link_to 'Back', posts_path %>
</erb>
-The +&lt;%= render 'form' %&gt;+ line is our first introduction to _partials_ in Rails. A partial is a snippet of HTML and Ruby code that can be reused in multiple locations. In this case, the form used to make a new post, is basically identical to a form used to edit a post, both have text fields for the name and title and a text area for the content with a button to make a new post or update the existing post.
+The +&lt;%= render 'form' %&gt;+ line is our first introduction to _partials_ in Rails. A partial is a snippet of HTML and Ruby code that can be reused in multiple locations. In this case, the form used to make a new post, is basically identical to a form used to edit a post, both have text fields for the name and title and a text area for the content with a button to make a new post or update the existing post.
If you take a look at +views/posts/_form.html.erb+ file, you will see the following:
@@ -653,13 +649,13 @@ def create
respond_to do |format|
if @post.save
- format.html { redirect_to(@post,
+ format.html { redirect_to(@post,
:notice => 'Post was successfully created.') }
- format.xml { render :xml => @post,
+ format.json { render :json => @post,
:status => :created, :location => @post }
else
- format.html { render :action => "new" }
- format.xml { render :xml => @post.errors,
+ format.html { render :action => "new" }
+ format.json { render :json => @post.errors,
:status => :unprocessable_entity }
end
end
@@ -681,8 +677,8 @@ def show
@post = Post.find(params[:id])
respond_to do |format|
- format.html # show.html.erb
- format.xml { render :xml => @post }
+ format.html # show.html.erb
+ format.json { render :json => @post }
end
end
</ruby>
@@ -743,12 +739,12 @@ def update
respond_to do |format|
if @post.update_attributes(params[:post])
- format.html { redirect_to(@post,
+ format.html { redirect_to(@post,
:notice => 'Post was successfully updated.') }
- format.xml { head :ok }
+ format.json { render :json => {}, :status => :ok }
else
- format.html { render :action => "edit" }
- format.xml { render :xml => @post.errors,
+ format.html { render :action => "edit" }
+ format.json { render :json => @post.errors,
:status => :unprocessable_entity }
end
end
@@ -767,8 +763,8 @@ def destroy
@post.destroy
respond_to do |format|
- format.html { redirect_to(posts_url) }
- format.xml { head :ok }
+ format.html { redirect_to(posts_url) }
+ format.json { render :json => {}, :status => :ok }
end
end
</ruby>
@@ -807,7 +803,7 @@ In addition to the model, Rails has also made a migration to create the correspo
<ruby>
class CreateComments < ActiveRecord::Migration
- def self.up
+ def change
create_table :comments do |t|
t.string :commenter
t.text :body
@@ -818,10 +814,6 @@ class CreateComments < ActiveRecord::Migration
add_index :comments, :post_id
end
-
- def self.down
- drop_table :comments
- end
end
</ruby>
@@ -873,7 +865,7 @@ TIP: For more information on Active Record associations, see the "Active Record
h4. Adding a Route for Comments
-As with the +home+ controller, we will need to add a route so that Rails knows where we would like to navigate to see +comments+. Open up the +config/routes.rb+ file again, you will see an entry that was added automatically for +posts+ near the top by the scaffold generator, +resources :posts+, edit it as follows:
+As with the +home+ controller, we will need to add a route so that Rails knows where we would like to navigate to see +comments+. Open up the +config/routes.rb+ file again, you will see an entry that was added automatically for +posts+ near the top by the scaffold generator, +resources :posts+, edit it as follows:
<ruby>
resources :posts do
@@ -901,7 +893,7 @@ This creates four files and one empty directory:
* +test/unit/helpers/comments_helper_test.rb+ - The unit tests for the helper
* +app/views/comments/+ - Views of the controller are stored here
-Like with any blog, our readers will create their comments directly after reading the post, and once they have added their comment, will be sent back to the post show page to see their comment now listed. Due to this, our +CommentsController+ is there to provide a method to create comments and delete SPAM comments when they arrive.
+Like with any blog, our readers will create their comments directly after reading the post, and once they have added their comment, will be sent back to the post show page to see their comment now listed. Due to this, our +CommentsController+ is there to provide a method to create comments and delete SPAM comments when they arrive.
So first, we'll wire up the Post show template (+/app/views/posts/show.html.erb+) to let us make a new comment:
@@ -1078,7 +1070,7 @@ Then in the +app/views/posts/show.html.erb+ you can change it to look like the f
<%= link_to 'Back to Posts', posts_path %> |
</erb>
-This will now render the partial in +app/views/comments/_comment.html.erb+ once for each comment that is in the +@post.comments+ collection. As the +render+ method iterates over the <tt>@post.comments</tt> collection, it assigns each comment to a local variable named the same as the partial, in this case +comment+ which is then available in the partial for us to show.
+This will now render the partial in +app/views/comments/_comment.html.erb+ once for each comment that is in the +@post.comments+ collection. As the +render+ method iterates over the <tt>@post.comments</tt> collection, it assigns each comment to a local variable named the same as the partial, in this case +comment+ which is then available in the partial for us to show.
h4. Rendering a Partial Form
@@ -1138,7 +1130,7 @@ The +@post+ object is available to any partials rendered in the view because we
h3. Deleting Comments
-Another important feature on a blog is being able to delete SPAM comments. To do this, we need to implement a link of some sort in the view and a +DELETE+ action in the +CommentsController+.
+Another important feature on a blog is being able to delete SPAM comments. To do this, we need to implement a link of some sort in the view and a +DELETE+ action in the +CommentsController+.
So first, let's add the delete link in the +app/views/comments/_comment.html.erb+ partial:
@@ -1201,36 +1193,19 @@ h3. Security
If you were to publish your blog online, anybody would be able to add, edit and delete posts or delete comments.
-Rails provides a very simple HTTP authentication system that will work nicely in this situation. First, we enable simple HTTP based authentication in our <tt>app/controllers/application_controller.rb</tt>:
-
-<ruby>
-class ApplicationController < ActionController::Base
- protect_from_forgery
-
- private
-
- def authenticate
- authenticate_or_request_with_http_basic do |user_name, password|
- user_name == 'admin' && password == 'password'
- end
- end
-
-end
-</ruby>
-
-You can obviously change the username and password to whatever you want. We put this method inside of +ApplicationController+ so that it is available to all of our controllers.
+Rails provides a very simple HTTP authentication system that will work nicely in this situation.
-Then in the +PostsController+ we need to have a way to block access to the various actions if the person is not authenticated, here we can use the Rails <tt>before_filter</tt> method, which allows us to specify that Rails must run a method and only then allow access to the requested action if that method allows it.
+In the +PostsController+ we need to have a way to block access to the various actions if the person is not authenticated, here we can use the Rails <tt>http_basic_authenticate_with</tt> method, allowing access to the requested action if that method allows it.
-To use the before filter, we specify it at the top of our +PostsController+, in this case, we want the user to be authenticated on every action, except for +index+ and +show+, so we write that:
+To use the authentication system, we specify it at the top of our +PostsController+, in this case, we want the user to be authenticated on every action, except for +index+ and +show+, so we write that:
<ruby>
class PostsController < ApplicationController
- before_filter :authenticate, :except => [:index, :show]
+ http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index
# GET /posts
- # GET /posts.xml
+ # GET /posts.json
def index
@posts = Post.all
respond_to do |format|
@@ -1242,7 +1217,7 @@ We also only want to allow authenticated users to delete comments, so in the +Co
<ruby>
class CommentsController < ApplicationController
- before_filter :authenticate, :only => :destroy
+ http_basic_authenticate_with :name => "dhh", :password => "secret", :only => :destroy
def create
@post = Post.find(params[:post_id])
@@ -1329,7 +1304,7 @@ Note that we have changed the +f+ in +form_for(@post) do |f|+ to +post_form+ to
This example shows another option of the render helper, being able to pass in local variables, in this case, we want the local variable +form+ in the partial to refer to the +post_form+ object.
-We also add a <tt>@post.tags.build</tt> at the top of this form, this is to make sure there is a new tag ready to have it's name filled in by the user. If you do not build the new tag, then the form will not appear as there is no new Tag object ready to create.
+We also add a <tt>@post.tags.build</tt> at the top of this form, this is to make sure there is a new tag ready to have it's name filled in by the user. If you do not build the new tag, then the form will not appear as there is no new Tag object ready to create.
Now create the folder <tt>app/views/tags</tt> and make a file in there called <tt>_form.html.erb</tt> which contains the form for the tag:
@@ -1390,7 +1365,7 @@ However, that method call <tt>@post.tags.map { |t| t.name }.join(", ")</tt> is a
h3. View Helpers
-View Helpers live in <tt>app/helpers</tt> and provide small snippets of reusable code for views. In our case, we want a method that strings a bunch of objects together using their name attribute and joining them with a comma. As this is for the Post show template, we put it in the PostsHelper.
+View Helpers live in <tt>app/helpers</tt> and provide small snippets of reusable code for views. In our case, we want a method that strings a bunch of objects together using their name attribute and joining them with a comma. As this is for the Post show template, we put it in the PostsHelper.
Open up <tt>app/helpers/posts_helper.rb</tt> and add the following:
@@ -1475,6 +1450,8 @@ Two very common sources of data that are not UTF-8:
h3. Changelog
+* April 26, 2011: Changed migration code from +up+, +down+ pair to +change+ method "Prem Sichanugrist":"http://sikachu.com"
+* April 11, 2011: Changed scaffold_controller generator to create format block for JSON instead of XML "Sebastian Martinez":http://www.wyeworks.com
* August 30, 2010: Minor editing after Rails 3 release by "Joost Baaij":http://www.spacebabies.nl
* July 12, 2010: Fixes, editing and updating of code samples by "Jaime Iniesta":http://jaimeiniesta.com
* May 16, 2010: Added a section on configuration gotchas to address common encoding problems that people might have by "Yehuda Katz":http://www.yehudakatz.com
diff --git a/railties/guides/source/i18n.textile b/railties/guides/source/i18n.textile
index 3e7e396e8d..608643b3d3 100644
--- a/railties/guides/source/i18n.textile
+++ b/railties/guides/source/i18n.textile
@@ -91,7 +91,7 @@ This means, that in the +:en+ locale, the key _hello_ will map to the _Hello wor
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-UK+, 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 +:cz+, +: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-UK+, 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-UK+ dictionary. Various "Rails I18n plugins":http://rails-i18n.org/wiki such as "Globalize2":https://github.com/joshmh/globalize2/tree/master may help you implement it.
+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-UK+, 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 +:cz+, +: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-UK+, 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-UK+ dictionary. Various "Rails I18n plugins":http://rails-i18n.org/wiki such as "Globalize2":https://github.com/joshmh/globalize2/tree/master may help you implement it.
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.
@@ -133,9 +133,9 @@ The _setting part_ is easy. You can set the locale in a +before_filter+ in the +
<ruby>
before_filter :set_locale
+
def set_locale
- # if params[:locale] is nil then I18n.default_locale will be used
- I18n.locale = params[:locale]
+ I18n.locale = params[:locale] || I18n.default_locale
end
</ruby>
@@ -158,7 +158,7 @@ You can implement it like this in your +ApplicationController+:
before_filter :set_locale
def set_locale
- I18n.locale = extract_locale_from_tld
+ I18n.locale = extract_locale_from_tld || I18n.default_locale
end
# Get locale from top-level domain or return nil if such locale is not available
@@ -182,7 +182,7 @@ We can also set the locale from the _subdomain_ in a very similar way:
# in your /etc/hosts file to try this out locally
def extract_locale_from_subdomain
parsed_locale = request.subdomains.first
- I18n.available_locales.include?(parsed_locale.to_sym) ? parsed_locale : nil
+ I18n.available_locales.include?(parsed_locale.to_sym) ? parsed_locale : nil
end
</ruby>
@@ -441,7 +441,7 @@ Do check the "Rails i18n Wiki":http://rails-i18n.org/wiki for list of tools avai
h3. Overview of the I18n API Features
-You should have good understanding of using the i18n library now, knowing all necessary aspects of internationalizing a basic Rails application. In the following chapters, we'll cover it's features in more depth.
+You should have good understanding of using the i18n library now, knowing all necessary aspects of internationalizing a basic Rails application. In the following chapters, we'll cover it's features in more depth.
Covered are features like these:
@@ -520,7 +520,7 @@ I18n.t 'activerecord.errors.messages'
h5. "Lazy" Lookup
-Rails 2.3 implements a convenient way to look up the locale inside _views_. When you have the following dictionary:
+Rails implements a convenient way to look up the locale inside _views_. When you have the following dictionary:
<yaml>
es:
@@ -863,7 +863,7 @@ If you find anything missing or wrong in this guide, please file a ticket on our
h3. 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-bread of most widely useful features for inclusion in the core.
+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!)
diff --git a/railties/guides/source/index.html.erb b/railties/guides/source/index.html.erb
index af46beee56..b48488d8a2 100644
--- a/railties/guides/source/index.html.erb
+++ b/railties/guides/source/index.html.erb
@@ -17,7 +17,7 @@ Ruby on Rails Guides
<% else %>
<p>
These are the new guides for Rails 3. The guides for Rails 2.3 are still available
- at <a href="http://guides.rubyonrails.org/v2.3.8/">http://guides.rubyonrails.org/v2.3.8/</a>.
+ at <a href="http://guides.rubyonrails.org/v2.3.11/">http://guides.rubyonrails.org/v2.3.11/</a>.
</p>
<% end %>
<p>
diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile
index 0cbbe1f389..638830cd83 100644
--- a/railties/guides/source/initialization.textile
+++ b/railties/guides/source/initialization.textile
@@ -468,7 +468,7 @@ h4. +config/application.rb+
This file requires +config/boot.rb+, but only if it hasn't been required before, which would be the case in +rails server+ but *wouldn't* be the case with Passenger.
-Then the fun begins!
+Then the fun begins!
h3. Loading Rails
@@ -478,8 +478,7 @@ The next line in +config/application.rb+ is:
require 'rails/all'
</ruby>
-h4 +railties/lib/rails/all.rb+
-
+h4. +railties/lib/rails/all.rb+
This file is responsible for requiring all the individual parts of Rails like so:
@@ -591,9 +590,13 @@ h4. +activesupport/lib/active_support/deprecation/behaviors.rb+
This file defines the behavior of the +ActiveSupport::Deprecation+ module, setting up the +DEFAULT_BEHAVIORS+ hash constant which contains the three defaults to outputting deprecation warnings: +:stderr+, +:log+ and +:notify+. This file begins by requiring +activesupport/notifications+ and +activesupport/core_ext/array/wrap+.
-h4 +activesupport/lib/active_support/notifications.rb+
+h4. +activesupport/lib/active_support/notifications.rb+
+
+This file defines the +ActiveSupport::Notifications+ module. Notifications provides an instrumentation API for Ruby, shipping with a queue implementation that consumes and publish events to log subscribers in a thread.
+
+The "API documentation":http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html for +ActiveSupport::Notifications+ explains the usage of this module, including the methods that it defines.
-TODO: document +ActiveSupport::Notifications+.
+The file required in +active_support/notifications.rb+ is +active_support/core_ext/module/delegation+ which is documented in the "Active Support Core Extensions Guide":http://guides.rubyonrails.org/active_support_core_extensions.html#method-delegation.
h4. +activesupport/core_ext/array/wrap+
@@ -661,7 +664,7 @@ The +active_support/inflector/methods+ file has already been required by +active
h4. +activesupport/lib/active_support/inflector/inflections.rb+
-This file references the +ActiveSupport::Inflector+ constant which isn't loaded by this point. But there were autoloads set up in +activesupport/lib/active_support.rb+ which will load the file which loads this constant and so then it will be defined. Then this file defines pluralization and singularization rules for words in Rails. This is how Rails knows how to pluralize "tomato" to "tomatoes".
+This file references the +ActiveSupport::Inflector+ constant which isn't loaded by this point. But there were autoloads set up in +activesupport/lib/active_support.rb+ which will load the file which loads this constant and so then it will be defined. Then this file defines pluralization and singularization rules for words in Rails. This is how Rails knows how to pluralize "tomato" to "tomatoes".
h4. +activesupport/lib/active_support/inflector/transliterate.rb+
@@ -695,7 +698,7 @@ h4. Back to +railties/lib/rails/plugin.rb+
The next file required in this is a core extension from Active Support called +array/conversions+ which is covered in "this section":http://guides.rubyonrails.org/active_support_core_extensions.html#array-conversions of the Active Support Core Extensions Guide.
-Once that file has finished loading, the +Rails::Plugin+ class is defined.
+Once that file has finished loading, the +Rails::Plugin+ class is defined.
h4. Back to +railties/lib/rails/application.rb+
@@ -705,7 +708,7 @@ Once this file's done then we go back to the +railties/lib/rails.rb+ file, which
h4. +railties/lib/rails/version.rb+
-Much like +active_support/version+, this file defines the +VERSION+ constant which has a +STRING+ constant on it which returns the current version of Rails.
+Much like +active_support/version+, this file defines the +VERSION+ constant which has a +STRING+ constant on it which returns the current version of Rails.
Once this file has finished loading we go back to +railties/lib/rails.rb+ which then requires +active_support/railtie.rb+.
@@ -923,7 +926,7 @@ This file defines the +ActionDispatch::Railtie+ class, but not before requiring
h4. +activesupport/lib/action_dispatch.rb+
-This file attempts to locate the +active_support+ and +active_model+ libraries by looking a couple of directories back from the current file and then adds the +active_support+ and +active_model+ +lib+ directories to the load path, but only if they aren't already, which they are.
+This file attempts to locate the +active_support+ and +active_model+ libraries by looking a couple of directories back from the current file and then adds the +active_support+ and +active_model+ +lib+ directories to the load path, but only if they aren't already, which they are.
<ruby>
activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__)
@@ -1006,7 +1009,7 @@ The loading of this file finishes the loading of +active_model+ and so we go bac
h4. Back to +activesupport/lib/action_dispatch.rb+
-The remainder of this file requires the +rack+ file from the Rack gem which defines the +Rack+ module. After +rack+, there's autoloads defined for the +Rack+, +ActionDispatch+, +ActionDispatch::Http+, +ActionDispatch::Session+. A new method called +autoload_under+ is used here, and this simply prefixes the files where the modules are autoloaded from with the path specified. For example here:
+The remainder of this file requires the +rack+ file from the Rack gem which defines the +Rack+ module. After +rack+, there's autoloads defined for the +Rack+, +ActionDispatch+, +ActionDispatch::Http+, +ActionDispatch::Session+. A new method called +autoload_under+ is used here, and this simply prefixes the files where the modules are autoloaded from with the path specified. For example here:
<ruby>
autoload_under 'testing' do
@@ -1109,4 +1112,4 @@ However the require after these is to a file that hasn't yet been loaded, +actio
h4. +actionpack/lib/action_view.rb+
-+action_view.rb+
++action_view.rb+
diff --git a/railties/guides/source/layout.html.erb b/railties/guides/source/layout.html.erb
index f2681c6461..911655e0f4 100644
--- a/railties/guides/source/layout.html.erb
+++ b/railties/guides/source/layout.html.erb
@@ -111,7 +111,7 @@
<h3>Feedback</h3>
<p>
- You're encouraged to help in keeping the quality of this guide.
+ You're encouraged to help improve the quality of this guide.
</p>
<p>
If you see any typos or factual errors you are confident to
diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile
index 1548da0eb5..d67668df91 100644
--- a/railties/guides/source/layouts_and_rendering.textile
+++ b/railties/guides/source/layouts_and_rendering.textile
@@ -90,7 +90,7 @@ If we want to display the properties of all the books in our view, we can do so
<%= link_to 'New book', new_book_path %>
</ruby>
-NOTE: The actual rendering is done by subclasses of +ActionView::TemplateHandlers+. This guide does not dig into that process, but it's important to know that the file extension on your view controls the choice of template handler. In Rails 2, the standard extensions are +.erb+ for ERB (HTML with embedded Ruby), +.rjs+ for RJS (JavaScript with embedded ruby) and +.builder+ for Builder (XML generator).
+NOTE: The actual rendering is done by subclasses of +ActionView::TemplateHandlers+. This guide does not dig into that process, but it's important to know that the file extension on your view controls the choice of template handler. In Rails 2, the standard extensions are +.erb+ for ERB (HTML with embedded Ruby), and +.builder+ for Builder (XML generator).
h4. Using +render+
@@ -250,18 +250,6 @@ render :inline =>
"xml.p {'Horrid coding practice!'}", :type => :builder
</ruby>
-h5. Using +render+ with +:update+
-
-You can also render JavaScript-based page updates inline using the +:update+ option to +render+:
-
-<ruby>
-render :update do |page|
- page.replace_html 'warning', "Invalid options supplied"
-end
-</ruby>
-
-WARNING: Placing JavaScript updates in your controller may seem to streamline small updates, but it defeats the MVC orientation of Rails and will make it harder for other developers to follow the logic of your project. We recommend using a separate RJS template instead, no matter how small the update.
-
h5. Rendering Text
You can send plain text - with no markup at all - back to the browser by using the +:text+ option to +render+:
@@ -296,7 +284,7 @@ TIP: You don't need to call +to_xml+ on the object that you want to render. If y
h5. Rendering Vanilla JavaScript
-Rails can render vanilla JavaScript (as an alternative to using +update+ with an +.rjs+ file):
+Rails can render vanilla JavaScript:
<ruby>
render :js => "alert('Hello Rails');"
@@ -406,7 +394,7 @@ end
Now, if the current user is a special user, they'll get a special layout when viewing a product. You can even use an inline method to determine the layout:
-You can also decide the layout by passing a Proc object, the block you give the Proc will be given the +controller+ instance, so you can make decisions based on the current request. For example:
+You can also decide the layout by passing a Proc object, the block you give the Proc will be given the +controller+ instance, so you can make decisions based on the current request. For example:
<ruby>
class ProductsController < ApplicationController
@@ -584,7 +572,7 @@ With this code, the browser will make a fresh request for the index page, the co
The only downside to this code, is that it requires a round trip to the browser, the browser requested the show action with +/books/1+ and the controller finds that there are no books, so the controller sends out a 302 redirect response to the browser telling it to go to +/books/+, the browser complies and sends a new request back to the controller asking now for the +index+ action, the controller then gets all the books in the database and renders the index template, sending it back down to the browser which then shows it on your screen.
-While in a small app, this added latency might not be a problem, it is something to think about when speed of response is of the essence. One way to handle this double request (though a contrived example) could be:
+While in a small app, this added latency might not be a problem, it is something to think about when speed of response is of the essence. One way to handle this double request (though a contrived example) could be:
<ruby>
def index
@@ -707,18 +695,28 @@ To include +http://example.com/main.js+:
<%= javascript_include_tag "http://example.com/main.js" %>
</erb>
-The +defaults+ option loads the Prototype and Scriptaculous libraries:
+If the application does not use the asset pipeline, the +:defaults+ option loads jQuery by default:
<erb>
<%= javascript_include_tag :defaults %>
</erb>
-The +all+ option loads every JavaScript file in +public/javascripts+, starting with the Prototype and Scriptaculous libraries:
+And you can in any case override the expansion in <tt>config/application.rb</tt>:
+
+<ruby>
+config.action_view.javascript_expansions[:defaults] = %w(foo.js bar.js)
+</ruby>
+
+When using <tt>:defaults</tt>, if an <tt>application.js</tt> file exists in <tt>public/javascripts</tt> it will be included as well at then end.
+
+Also, the +:all+ option loads every JavaScript file in +public/javascripts+:
<erb>
<%= javascript_include_tag :all %>
</erb>
+Note that your defaults of choice will be included first, so they will be available to all subsequently included files.
+
You can supply the +:recursive+ option to load files in subfolders of +public/javascripts+ as well:
<erb>
@@ -862,7 +860,7 @@ Produces
<video src="/videos/movie.ogg" />
</erb>
-Like an +image_tag+ you can supply a path, either absolute, or relative to the +public/videos+ directory. Additionally you can specify the +:size => "#{width}x#{height}"+ option just like an +image_tag+. Video tags can also have any of the HTML options specified at the end (+id+, +class+ et al).
+Like an +image_tag+ you can supply a path, either absolute, or relative to the +public/videos+ directory. Additionally you can specify the +:size => "#{width}x#{height}"+ option just like an +image_tag+. Video tags can also have any of the HTML options specified at the end (+id+, +class+ et al).
The video tag also supports all of the +&lt;video&gt;+ HTML options through the HTML options hash, including:
@@ -1135,7 +1133,7 @@ You can also pass in arbitrary local variables to any partial you are rendering
Would render a partial +_products.html.erb+ once for each instance of +product+ in the +@products+ instance variable passing the instance to the partial as a local variable called +item+ and to each partial, make the local variable +title+ available with the value +Products Page+.
-TIP: Rails also makes a counter variable available within a partial called by the collection, named after the member of the collection followed by +_counter+. For example, if you're rendering +@products+, within the partial you can refer to +product_counter+ to tell you how many times the partial has been rendered. This does not work in conjunction with the +:as => :value+ option.
+TIP: Rails also makes a counter variable available within a partial called by the collection, named after the member of the collection followed by +_counter+. For example, if you're rendering +@products+, within the partial you can refer to +product_counter+ to tell you how many times the partial has been rendered. This does not work in conjunction with the +:as => :value+ option.
You can also specify a second partial to be rendered between instances of the main partial by using the +:spacer_template+ option:
diff --git a/railties/guides/source/migrations.textile b/railties/guides/source/migrations.textile
index 57e6bcd123..27f8a9303e 100644
--- a/railties/guides/source/migrations.textile
+++ b/railties/guides/source/migrations.textile
@@ -21,7 +21,7 @@ Before I dive into the details of a migration, here are a few examples of the so
<ruby>
class CreateProducts < ActiveRecord::Migration
- def self.up
+ def up
create_table :products do |t|
t.string :name
t.text :description
@@ -30,7 +30,7 @@ class CreateProducts < ActiveRecord::Migration
end
end
- def self.down
+ def down
drop_table :products
end
end
@@ -42,14 +42,14 @@ Migrations are not limited to changing the schema. You can also use them to fix
<ruby>
class AddReceiveNewsletterToUsers < ActiveRecord::Migration
- def self.up
+ def up
change_table :users do |t|
t.boolean :receive_newsletter, :default => false
end
User.update_all ["receive_newsletter = ?", true]
end
- def self.down
+ def down
remove_column :users, :receive_newsletter
end
end
@@ -58,6 +58,21 @@ end
This migration adds a +receive_newsletter+ column to the +users+ table. We want it to default to +false+ for new users, but existing users are considered
to have already opted in, so we use the User model to set the flag to +true+ for existing users.
+Rails 3.1 makes migrations smarter by providing a new <tt>change</tt> method. This method is preferred for writing constructive migrations (adding columns or tables). The migration knows how to migrate your database and reverse it when the migration is rolled back without the need to write a separate +down+ method.
+
+<ruby>
+class CreateProducts < ActiveRecord::Migration
+ def change
+ create_table :products do |t|
+ t.string :name
+ t.text :description
+
+ t.timestamps
+ end
+ end
+end
+</ruby>
+
NOTE: Some "caveats":#using-models-in-your-migrations apply to using models in your migrations.
h4. Migrations are Classes
@@ -116,7 +131,7 @@ will create a migration that looks like this
<ruby>
class CreateProducts < ActiveRecord::Migration
- def self.up
+ def change
create_table :products do |t|
t.string :name
t.text :description
@@ -124,10 +139,6 @@ class CreateProducts < ActiveRecord::Migration
t.timestamps
end
end
-
- def self.down
- drop_table :products
- end
end
</ruby>
@@ -146,10 +157,7 @@ This will create an empty but appropriately named migration:
<ruby>
class AddPartNumberToProducts < ActiveRecord::Migration
- def self.up
- end
-
- def self.down
+ def change
end
end
</ruby>
@@ -164,13 +172,9 @@ will generate
<ruby>
class AddPartNumberToProducts < ActiveRecord::Migration
- def self.up
+ def change
add_column :products, :part_number, :string
end
-
- def self.down
- remove_column :products, :part_number
- end
end
</ruby>
@@ -184,11 +188,11 @@ generates
<ruby>
class RemovePartNumberFromProducts < ActiveRecord::Migration
- def self.up
+ def up
remove_column :products, :part_number
end
- def self.down
+ def down
add_column :products, :part_number, :string
end
end
@@ -204,20 +208,17 @@ generates
<ruby>
class AddDetailsToProducts < ActiveRecord::Migration
- def self.up
+ def change
add_column :products, :part_number, :string
add_column :products, :price, :decimal
end
-
- def self.down
- remove_column :products, :price
- remove_column :products, :part_number
- end
end
</ruby>
As always, what has been generated for you is just a starting point. You can add or remove from it as you see fit.
+NOTE: The generated migration file for destructive migrations will still be old-style using the +up+ and +down+ methods. This is because Rails doesn't know the original data types defined when you made the original changes.
+
h3. Writing a Migration
Once you have created your migration using one of the generators it's time to get to work!
@@ -284,7 +285,7 @@ change_table :products do |t|
t.rename :upccode, :upc_code
end
</ruby>
-removes the +description+ and +name+ columns, creates a +part_number+ column and adds an index on it. Finally it renames the +upccode+ column. This is the same as doing
+removes the +description+ and +name+ columns, creates a +part_number+ column and adds an index on it. Finally it renames the +upccode+ column. This is the same as doing
<ruby>
remove_column :products, :description
@@ -335,7 +336,22 @@ NOTE: The +references+ helper does not actually create foreign key constraints f
If the helpers provided by Active Record aren't enough you can use the +execute+ function to execute arbitrary SQL.
-For more details and examples of individual methods check the API documentation, in particular the documentation for "<tt>ActiveRecord::ConnectionAdapters::SchemaStatements</tt>":http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html (which provides the methods available in the +up+ and +down+ methods), "<tt>ActiveRecord::ConnectionAdapters::TableDefinition</tt>":http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html (which provides the methods available on the object yielded by +create_table+) and "<tt>ActiveRecord::ConnectionAdapters::Table</tt>":http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html (which provides the methods available on the object yielded by +change_table+).
+For more details and examples of individual methods check the API documentation, in particular the documentation for "<tt>ActiveRecord::ConnectionAdapters::SchemaStatements</tt>":http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html (which provides the methods available in the +up+ and +down+ methods), "<tt>ActiveRecord::ConnectionAdapters::TableDefinition</tt>":http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html (which provides the methods available on the object yielded by +create_table+) and "<tt>ActiveRecord::ConnectionAdapters::Table</tt>":http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html (which provides the methods available on the object yielded by +change_table+).
+
+h4. Writing Your +change+ Method
+
+The +change+ method removes the need to write both +up+ and +down+ methods in those cases that Rails know how to revert the changes automatically. Currently, the +change+ method supports only these migration definitions:
+
+* +add_column+
+* +add_index+
+* +add_timestamp+
+* +create_table+
+* +remove_timestamps+
+* +rename_column+
+* +rename_index+
+* +rename_table+
+
+If you're going to use other methods, you'll have to write the +up+ and +down+ methods normally.
h4. Writing Your +down+ Method
@@ -344,7 +360,7 @@ The +down+ method of your migration should revert the transformations done by th
<ruby>
class ExampleMigration < ActiveRecord::Migration
- def self.up
+ def up
create_table :products do |t|
t.references :category
end
@@ -361,7 +377,7 @@ class ExampleMigration < ActiveRecord::Migration
rename_column :users, :email, :email_address
end
- def self.down
+ def down
rename_column :users, :email_address, :email
remove_column :users, :home_page_url
execute "ALTER TABLE products DROP FOREIGN KEY fk_products_categories"
@@ -369,9 +385,8 @@ class ExampleMigration < ActiveRecord::Migration
end
end
</ruby>
-Sometimes your migration will do something which is just plain irreversible, for example it might destroy some data. In cases like those when you can't reverse the migration you can raise +IrreversibleMigration+ from your +down+ method. If someone tries to revert your migration an error message will be
-displayed saying that it can't be done.
+Sometimes your migration will do something which is just plain irreversible, for example it might destroy some data. In cases like those when you can't reverse the migration you can raise +IrreversibleMigration+ from your +down+ method. If someone tries to revert your migration an error message will be displayed saying that it can't be done.
h3. Running Migrations
@@ -449,7 +464,7 @@ For example, this migration
<ruby>
class CreateProducts < ActiveRecord::Migration
- def self.up
+ def change
suppress_messages do
create_table :products do |t|
t.string :name
@@ -465,10 +480,6 @@ class CreateProducts < ActiveRecord::Migration
250
end
end
-
- def self.down
- drop_table :products
- end
end
</ruby>
@@ -499,11 +510,7 @@ class AddPartNumberToProducts < ActiveRecord::Migration
class Product < ActiveRecord::Base
end
- def self.up
- ...
- end
-
- def self.down
+ def change
...
end
end
@@ -519,15 +526,11 @@ class AddPartNumberToProducts < ActiveRecord::Migration
class Product < ActiveRecord::Base
end
- def self.up
+ def change
add_column :product, :part_number, :string
Product.reset_column_information
...
end
-
- def self.down
- ...
- end
end
</ruby>
@@ -590,5 +593,6 @@ Although Active Record does not provide any tools for working directly with such
h3. Changelog
+* April 26, 2011: change generated +up+ and +down+ methods to +change+ method, and describe detail about +change+ method by "Prem Sichanugrist":http://sikachu.com
* July 15, 2010: minor typos corrected by "Jaime Iniesta":http://jaimeiniesta.com
* September 14, 2008: initial version by "Frederick Cheung":credits.html#fcheung
diff --git a/railties/guides/source/plugins.textile b/railties/guides/source/plugins.textile
index 2d9821e627..d486e8ade3 100644
--- a/railties/guides/source/plugins.textile
+++ b/railties/guides/source/plugins.textile
@@ -17,8 +17,8 @@ This guide describes how to build a test-driven plugin that will:
* Add methods to ActiveRecord::Base in the tradition of the 'acts_as' plugins
* Give you information about where to put generators in your plugin.
-For the purpose of this guide pretend for a moment that you are an avid bird watcher.
-Your favorite bird is the Yaffle, and you want to create a plugin that allows other developers to share in the Yaffle
+For the purpose of this guide pretend for a moment that you are an avid bird watcher.
+Your favorite bird is the Yaffle, and you want to create a plugin that allows other developers to share in the Yaffle
goodness.
endprologue.
@@ -27,21 +27,21 @@ h3. Setup
h4. Generating the Plugin Skeleton
-Rails currently ships with a generator to generate a plugin within a Rails application. Help text is available that will explain
+Rails currently ships with a generator to generate a plugin within a Rails application. Help text is available that will explain
how this generator works.
<shell>
$ rails generate plugin --help
</shell>
-This generator places the plugin into the vendor/plugins directory.
+This generator places the plugin into the vendor/plugins directory.
-Vendored plugins are useful for quickly prototyping your plugin but current thinking in the Rails community is shifting towards
+Vendored plugins are useful for quickly prototyping your plugin but current thinking in the Rails community is shifting towards
packaging plugins as gems, especially with the inclusion of Bundler as the Rails dependency manager.
Packaging a plugin as a gem may be overkill for any plugins that will not be shared across projects but doing so from the start makes it easier to share the plugin going forward without adding too much additional overhead during development.
Rails 3.1 will ship with a plugin generator that will default to setting up a plugin
-as a gem. This tutorial will begin to bridge that gap by demonstrating how to create a gem based plugin using the
+as a gem. This tutorial will begin to bridge that gap by demonstrating how to create a gem based plugin using the
"Enginex gem":http://www.github.com/josevalim/enginex.
<shell>
@@ -69,7 +69,7 @@ h3. Extending Core Classes
This section will explain how to add a method to String that will be available anywhere in your rails application.
-In this example you will add a method to String named +to_squawk+. To begin, create a new test file with a few assertions:
+In this example you will add a method to String named +to_squawk+. To begin, create a new test file with a few assertions:
<ruby>
# yaffle/test/core_ext_test.rb
@@ -83,7 +83,7 @@ class CoreExtTest < Test::Unit::TestCase
end
</ruby>
-Run +rake+ to run the test. This test should fail because we haven't implemented the +to_squak+ method:
+Run +rake+ to run the test. This test should fail because we haven't implemented the +to_squak+ method:
<shell>
1) Error:
@@ -133,7 +133,7 @@ $ rails console
h3. Add an "acts_as" Method to Active Record
-A common pattern in plugins is to add a method called 'acts_as_something' to models. In this case, you
+A common pattern in plugins is to add a method called 'acts_as_something' to models. In this case, you
want to write a method called 'acts_as_yaffle' that adds a 'squawk' method to your Active Record models.
To begin, set up your files so that you have:
@@ -169,9 +169,9 @@ end
h4. Add a Class Method
-This plugin will expect that you've added a method to your model named 'last_squawk'. However, the
-plugin users might have already defined a method on their model named 'last_squawk' that they use
-for something else. This plugin will allow the name to be changed by adding a class method called 'yaffle_text_field'.
+This plugin will expect that you've added a method to your model named 'last_squawk'. However, the
+plugin users might have already defined a method on their model named 'last_squawk' that they use
+for something else. This plugin will allow the name to be changed by adding a class method called 'yaffle_text_field'.
To start out, write a failing test that shows the behavior you'd like:
@@ -210,7 +210,7 @@ When you run +rake+, you should see the following:
</shell>
This tells us that we don't have the necessary models (Hickwall and Wickwall) that we are trying to test.
-We can easily generate these models in our "dummy" Rails application by running the following commands from the
+We can easily generate these models in our "dummy" Rails application by running the following commands from the
test/dummy directory:
<shell>
@@ -220,7 +220,7 @@ $ rails generate model Wickwall last_squak:string last_tweet:string
</shell>
Now you can create the necessary database tables in your testing database by navigating to your dummy app
-and migrating the database. First
+and migrating the database. First
<shell>
$ cd test/dummy
@@ -319,7 +319,7 @@ When you run +rake+ you should see the tests all pass:
h4. Add an Instance Method
-This plugin will add a method named 'squawk' to any Active Record objects that call 'acts_as_yaffle'. The 'squawk'
+This plugin will add a method named 'squawk' to any Active Record objects that call 'acts_as_yaffle'. The 'squawk'
method will simply set the value of one of the fields in the database.
To start out, write a failing test that shows the behavior you'd like:
@@ -352,7 +352,7 @@ class ActsAsYaffleTest < Test::Unit::TestCase
end
</ruby>
-Run the test to make sure the last two tests fail the an error that contains "NoMethodError: undefined method `squawk'",
+Run the test to make sure the last two tests fail the an error that contains "NoMethodError: undefined method `squawk'",
then update 'acts_as_yaffle.rb' to look like this:
<ruby>
@@ -387,18 +387,18 @@ Run +rake+ one final time and you should see:
7 tests, 7 assertions, 0 failures, 0 errors, 0 skips
</shell>
-NOTE: The use of +write_attribute+ to write to the field in model is just one example of how a plugin can
-interact with the model, and will not always be the right method to use. For example, you could also
+NOTE: The use of +write_attribute+ to write to the field in model is just one example of how a plugin can
+interact with the model, and will not always be the right method to use. For example, you could also
use +send("#{self.class.yaffle_text_field}=", string.to_squawk)+.
h3. Generators
-Generators can be included in your gem simply by creating them in a lib/generators directory of your plugin. More information about
+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
h3. Publishing your Gem
-Gem plugins in progress can be easily be shared from any Git repository. To share the Yaffle gem with others, simply
+Gem plugins in progress can be easily be shared from any Git repository. To share the Yaffle gem with others, simply
commit the code to a Git repository (like Github) and add a line to the Gemfile of the any application:
<ruby>
@@ -412,7 +412,7 @@ For more information about publishing gems to RubyGems, see: "http://blog.thepet
h3. Non-Gem Plugins
-Non-gem plugins are useful for functionality that won't be shared with another project. Keeping your custom functionality in the
+Non-gem plugins are useful for functionality that won't be shared with another project. Keeping your custom functionality in the
vendor/plugins directory un-clutters the rest of the application.
Move the directory that you created for the gem based plugin into the vendor/plugins directory of a generated Rails application, create a vendor/plugins/yaffle/init.rb file that contains "require 'yaffle'" and everything will still work.
@@ -423,7 +423,7 @@ Move the directory that you created for the gem based plugin into the vendor/plu
require 'yaffle'
</ruby>
-You can test this by changing to the Rails application that you added the plugin to and starting a rails console. Once in the
+You can test this by changing to the Rails application that you added the plugin to and starting a rails console. Once in the
console we can check to see if the String has an instance method of to_squawk.
<shell>
$ cd my_app
@@ -435,7 +435,7 @@ You can also remove the .gemspec, Gemfile and Gemfile.lock files as they will no
h3. RDoc Documentation
-Once your plugin is stable and you are ready to deploy do everyone else a favor and document it! Luckily, writing documentation for your plugin is easy.
+Once your plugin is stable and you are ready to deploy do everyone else a favor and document it! Luckily, writing documentation for your plugin is easy.
The first step is to update the README file with detailed information about how to use your plugin. A few key things to include are:
diff --git a/railties/guides/source/rails_application_templates.textile b/railties/guides/source/rails_application_templates.textile
index 8e51f9e23b..388d8eea3e 100644
--- a/railties/guides/source/rails_application_templates.textile
+++ b/railties/guides/source/rails_application_templates.textile
@@ -11,19 +11,19 @@ endprologue.
h3. Usage
-To apply a template, you need to provide the Rails generator with the location of the template you wish to apply, using -m option :
+To apply a template, you need to provide the Rails generator with the location of the template you wish to apply, using -m option:
<shell>
$ rails new blog -m ~/template.rb
</shell>
-It's also possible to apply a template using a URL :
+It's also possible to apply a template using a URL:
<shell>
$ rails new blog -m https://gist.github.com/755496.txt
</shell>
-Alternatively, you can use the rake task +rails:template+ to apply a template to an existing Rails application :
+Alternatively, you can use the rake task +rails:template+ to apply a template to an existing Rails application:
<shell>
$ rake rails:template LOCATION=~/template.rb
@@ -31,7 +31,7 @@ $ rake rails:template LOCATION=~/template.rb
h3. Template API
-Rails templates API is very self explanatory and easy to understand. Here's an example of a typical Rails template :
+Rails templates API is very self explanatory and easy to understand. Here's an example of a typical Rails template:
<ruby>
# template.rb
@@ -45,20 +45,20 @@ git :add => "."
git :commit => "-a -m 'Initial commit'"
</ruby>
-The following sections outlines the primary methods provided by the API :
+The following sections outlines the primary methods provided by the API:
h4. gem(name, options = {})
Adds a +gem+ entry for the supplied gem to the generated application’s +Gemfile+.
-For example, if your application depends on the gems +bj+ and +nokogiri+ :
+For example, if your application depends on the gems +bj+ and +nokogiri+:
<ruby>
gem "bj"
gem "nokogiri"
</ruby>
-Please note that this will NOT install the gems for you. So you may want to run the +rake gems:install+ task too :
+Please note that this will NOT install the gems for you. So you may want to run the +rake gems:install+ task too:
<ruby>
rake "gems:install"
@@ -80,13 +80,13 @@ h4. plugin(name, options = {})
Installs a plugin to the generated application.
-Plugin can be installed from Git :
+Plugin can be installed from Git:
<ruby>
plugin 'authentication', :git => 'git://github.com/foor/bar.git'
</ruby>
-You can even install plugins as git submodules :
+You can even install plugins as git submodules:
<ruby>
plugin 'authentication', :git => 'git://github.com/foor/bar.git',
@@ -95,7 +95,7 @@ plugin 'authentication', :git => 'git://github.com/foor/bar.git',
Please note that you need to +git :init+ before you can install a plugin as a submodule.
-Or use plain old SVN :
+Or use plain old SVN:
<ruby>
plugin 'usingsvn', :svn => 'svn://example.com/usingsvn/trunk'
@@ -105,7 +105,7 @@ h4. vendor/lib/file/initializer(filename, data = nil, &block)
Adds an initializer to the generated application’s +config/initializers+ directory.
-Lets say you like using +Object#not_nil?+ and +Object#not_blank?+ :
+Lets say you like using +Object#not_nil?+ and +Object#not_blank?+:
<ruby>
initializer 'bloatlol.rb', <<-CODE
@@ -123,7 +123,7 @@ CODE
Similarly +lib()+ creates a file in the +lib/+ directory and +vendor()+ creates a file in the +vendor/+ directory.
-There is even +file()+, which accepts a relative path from +Rails.root+ and creates all the directories/file needed :
+There is even +file()+, which accepts a relative path from +Rails.root+ and creates all the directories/file needed:
<ruby>
file 'app/components/foo.rb', <<-CODE
@@ -136,7 +136,7 @@ That’ll create +app/components+ directory and put +foo.rb+ in there.
h4. rakefile(filename, data = nil, &block)
-Creates a new rake file under +lib/tasks+ with the supplied tasks :
+Creates a new rake file under +lib/tasks+ with the supplied tasks:
<ruby>
rakefile("bootstrap.rake") do
@@ -154,7 +154,7 @@ The above creates +lib/tasks/bootstrap.rake+ with a +boot:strap+ rake task.
h4. generate(what, args)
-Runs the supplied rails generator with given arguments. For example, I love to scaffold some whenever I’m playing with Rails :
+Runs the supplied rails generator with given arguments. For example, I love to scaffold some whenever I’m playing with Rails:
<ruby>
generate(:scaffold, "person", "name:string", "address:text", "age:number")
@@ -162,7 +162,7 @@ generate(:scaffold, "person", "name:string", "address:text", "age:number")
h4. run(command)
-Executes an arbitrary command. Just like the backticks. Let's say you want to remove the +public/index.html+ file :
+Executes an arbitrary command. Just like the backticks. Let's say you want to remove the +public/index.html+ file:
<ruby>
run "rm public/index.html"
@@ -170,19 +170,19 @@ run "rm public/index.html"
h4. rake(command, options = {})
-Runs the supplied rake tasks in the Rails application. Let's say you want to migrate the database :
+Runs the supplied rake tasks in the Rails application. Let's say you want to migrate the database:
<ruby>
rake "db:migrate"
</ruby>
-You can also run rake tasks with a different Rails environment :
+You can also run rake tasks with a different Rails environment:
<ruby>
rake "db:migrate", :env => 'production'
</ruby>
-Or even use sudo :
+Or even use sudo:
<ruby>
rake "gems:install", :sudo => true
@@ -190,7 +190,7 @@ rake "gems:install", :sudo => true
h4. route(routing_code)
-This adds a routing entry to the +config/routes.rb+ file. In above steps, we generated a person scaffold and also removed +public/index.html+. Now to make +PeopleController#index+ as the default page for the application :
+This adds a routing entry to the +config/routes.rb+ file. In above steps, we generated a person scaffold and also removed +public/index.html+. Now to make +PeopleController#index+ as the default page for the application:
<ruby>
route "root :to => 'person#index'"
@@ -208,7 +208,7 @@ end
h4. ask(question)
-+ask()+ gives you a chance to get some feedback from the user and use it in your templates. Lets say you want your user to name the new shiny library you’re adding :
++ask()+ gives you a chance to get some feedback from the user and use it in your templates. Lets say you want your user to name the new shiny library you’re adding:
<ruby>
lib_name = ask("What do you want to call the shiny library ?")
@@ -222,7 +222,7 @@ CODE
h4. yes?(question) or no?(question)
-These methods let you ask questions from templates and decide the flow based on the user’s answer. Lets say you want to freeze rails only if the user want to :
+These methods let you ask questions from templates and decide the flow based on the user’s answer. Lets say you want to freeze rails only if the user want to:
<ruby>
rake("rails:freeze:gems") if yes?("Freeze rails gems ?")
@@ -231,7 +231,7 @@ no?(question) acts just the opposite.
h4. git(:must => "-a love")
-Rails templates let you run any git command :
+Rails templates let you run any git command:
<ruby>
git :init
diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile
index 58b75b9a1d..99fdcee68a 100644
--- a/railties/guides/source/routing.textile
+++ b/railties/guides/source/routing.textile
@@ -321,7 +321,7 @@ resources :photos do
end
</ruby>
-This will recognize +/photos/1/preview+ with GET, and route to the +preview+ action of +PhotosController+. It will also create the +preview_photo_url+ and +preview_photo_path+ helpers.
+This will recognize +/photos/1/preview+ with GET, and route to the +preview+ action of +PhotosController+. It will also create the +preview_photo_url+ and +preview_photo_path+ helpers.
Within the block of member routes, each route name specifies the HTTP verb that it will recognize. You can use +get+, +put+, +post+, or +delete+ here. If you don't have multiple +member+ routes, you can also pass +:on+ to a route, eliminating the block:
@@ -391,7 +391,7 @@ NOTE: You can't use +namespace+ or +:module+ with a +:controller+ path segment.
match ':controller(/:action(/:id))', :controller => /admin\/[^\/]+/
</ruby>
-TIP: By default dynamic segments don't accept dots - this is because the dot is used as a separator for formatted routes. If you need to use a dot within a dynamic segment add a constraint which overrides this - for example +:id => /[^\/]<plus>/+ allows anything except a slash.
+TIP: By default dynamic segments don't accept dots - this is because the dot is used as a separator for formatted routes. If you need to use a dot within a dynamic segment add a constraint which overrides this - for example +:id+ => /[^\/]+/ allows anything except a slash.
h4. Static Segments
@@ -421,7 +421,7 @@ You do not need to explicitly use the +:controller+ and +:action+ symbols within
match 'photos/:id' => 'photos#show'
</ruby>
-With this route, Rails will match an incoming path of +/photos/12+ to the +show+ action of +PhotosController+.
+With this route, Rails will match an incoming path of +/photos/12+ to the +show+ action of +PhotosController+.
You can also define other defaults in a route by supplying a hash for the +:defaults+ option. This even applies to parameters that you do not specify as dynamic segments. For example:
@@ -557,7 +557,7 @@ match '*a/foo/*b' => 'test#index'
would match +zoo/woo/foo/bar/baz+ with +params[:a]+ equals +"zoo/woo"+, and +params[:b]+ equals +"bar/baz"+.
-NOTE: Starting from Rails 3.1, wildcard route will always matching the optional format segment by default. For example if you have this route:
+NOTE: Starting from Rails 3.1, wildcard routes will always match the optional format segment by default. For example if you have this route:
<ruby>
map '*pages' => 'pages#show'
@@ -660,7 +660,7 @@ end
NOTE: Of course, you can use the more advanced constraints available in non-resourceful routes in this context.
-TIP: By default the +:id+ parameter doesn't accept dots - this is because the dot is used as a separator for formatted routes. If you need to use a dot within an +:id+ add a constraint which overrides this - for example +:id => /[^\/]+/+ allows anything except a slash.
+TIP: By default the +:id+ parameter doesn't accept dots - this is because the dot is used as a separator for formatted routes. If you need to use a dot within an +:id+ add a constraint which overrides this - for example +:id+ => /[^\/]+/ allows anything except a slash.
h4. Overriding the Named Helpers
diff --git a/railties/guides/source/ruby_on_rails_guides_guidelines.textile b/railties/guides/source/ruby_on_rails_guides_guidelines.textile
index 6576758856..26a5a4c3c9 100644
--- a/railties/guides/source/ruby_on_rails_guides_guidelines.textile
+++ b/railties/guides/source/ruby_on_rails_guides_guidelines.textile
@@ -10,7 +10,7 @@ Guides are written in "Textile":http://www.textism.com/tools/textile/. There's c
h3. 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 readers what's the guide about, and what will they 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.
h3. Titles
@@ -23,7 +23,7 @@ h5. Middleware Stack is an Array
h5. When are Objects Saved?
</plain>
-Use same typography as in regular text:
+Use the same typography as in regular text:
<plain>
h6. The +:content_type+ Option
@@ -42,13 +42,13 @@ Those guidelines apply also to guides.
h3. HTML Generation
-To generate all the guides just cd into the +railties+ directory and execute
+To generate all the guides, just +cd+ into the +railties+ directory and execute:
<plain>
bundle exec rake generate_guides
</plain>
-You'll need the gems erubis, i18n, and RedCloth.
+(You may need to run +bundle install+ first to install the required gems.)
To process +my_guide.textile+ and nothing else use the +ONLY+ environment variable:
@@ -56,13 +56,13 @@ To process +my_guide.textile+ and nothing else use the +ONLY+ environment variab
bundle exec rake generate_guides ONLY=my_guide
</plain>
-Although by default guides that have not been modified are not processed, so +ONLY+ is rarely needed in practice.
+By default, guides that have not been modified are not processed, so +ONLY+ is rarely needed in practice.
To force process of all the guides, pass +ALL=1+.
-It is also recommended that you work with +WARNINGS=1+, this detects duplicate IDs and warns about broken internal links.
+It is also recommended that you work with +WARNINGS=1+. This detects duplicate IDs and warns about broken internal links.
-If you want to generate guides in languages other than English, you can keep them in a separate directory under +source+ (eg. <tt>source/es</tt>) and use the +LANGUAGE+ environment variable.
+If you want to generate guides in languages other than English, you can keep them in a separate directory under +source+ (eg. <tt>source/es</tt>) and use the +LANGUAGE+ environment variable:
<plain>
rake generate_guides LANGUAGE=es
@@ -70,7 +70,7 @@ rake generate_guides LANGUAGE=es
h3. HTML Validation
-Please do validate the generated HTML with
+Please validate the generated HTML with:
<plain>
rake validate_guides
@@ -80,4 +80,5 @@ Particularly, titles get an ID generated from their content and this often leads
h3. Changelog
+* March 31, 2011: grammar tweaks by "Josiah Ivey":http://twitter.com/josiahivey
* October 5, 2010: ported from the docrails wiki and revised by "Xavier Noria":credits.html#fxn
diff --git a/railties/guides/source/security.textile b/railties/guides/source/security.textile
index 893f65856c..8c408ec06b 100644
--- a/railties/guides/source/security.textile
+++ b/railties/guides/source/security.textile
@@ -147,7 +147,7 @@ reset_session
If you use the popular RestfulAuthentication plugin for user management, add reset_session to the SessionsController#create action. Note that this removes any value from the session, _(highlight)you have to transfer them to the new session_.
-Another countermeasure is to _(highlight)save user-specific properties in the session_, verify them every time a request comes in, and deny access, if the information does not match. Such properties could be the remote IP address or the user agent (the web browser name), though the latter is less user-specific. When saving the IP address, you have to bear in mind that there are Internet service providers or large organizations that put their users behind proxies. _(highlight)These might change over the course of a session_, so these users will not be able to use your application, or only in a limited way.
+Another countermeasure is to _(highlight)save user-specific properties in the session_, verify them every time a request comes in, and deny access, if the information does not match. Such properties could be the remote IP address or the user agent (the web browser name), though the latter is less user-specific. When saving the IP address, you have to bear in mind that there are Internet service providers or large organizations that put their users behind proxies. _(highlight)These might change over the course of a session_, so these users will not be able to use your application, or only in a limited way.
h4. Session Expiry
@@ -211,15 +211,7 @@ The HTTP protocol basically provides two main types of requests - GET and POST (
If your web application is RESTful, you might be used to additional HTTP verbs, such as PUT or DELETE. Most of today‘s web browsers, however do not support them - only GET and POST. Rails uses a hidden +_method+ field to handle this barrier.
-_(highlight)The verify method in a controller can make sure that specific actions may not be used over GET_. Here is an example to verify the use of the transfer action over POST. If the action comes in using any other verb, it redirects to the list action.
-
-<ruby>
-verify :method => :post, :only => [:transfer], :redirect_to => {:action => :list}
-</ruby>
-
-With this precaution, the attack from above will not work, because the browser sends a GET request for images, which will not be accepted by the web application.
-
-But this was only the first step, because _(highlight)POST requests can be sent automatically, too_. Here is an example for a link which displays www.harmless.com as destination in the browser's status bar. In fact it dynamically creates a new form that sends a POST request.
+_(highlight)POST requests can be sent automatically, too_. Here is an example for a link which displays www.harmless.com as destination in the browser's status bar. In fact it dynamically creates a new form that sends a POST request.
<html>
<a href="http://www.harmless.com/" onclick="
@@ -238,7 +230,7 @@ Or the attacker places the code into the onmouseover event handler of an image:
<img src="http://www.harmless.com/img" width="400" height="400" onmouseover="..." />
</html>
-There are many other possibilities, including Ajax to attack the victim in the background.
The _(highlight)solution to this is including a security token in non-GET requests_ which check on the server-side. In Rails 2 or higher, this is a one-liner in the application controller:
+There are many other possibilities, including Ajax to attack the victim in the background.
The _(highlight)solution to this is including a security token in non-GET requests_ which check on the server-side. In Rails 2 or higher, this is a one-liner in the application controller:
<ruby>
protect_from_forgery :secret => "123456789012345678901234567890..."
@@ -394,7 +386,7 @@ params[:user] # => {:name => “ow3ned”, :admin => true}
So if you create a new user using mass-assignment, it may be too easy to become an administrator.
-Note that this vulnerability is not restricted to database columns. Any setter method, unless explicitly protected, is accessible via the <tt>attributes=</tt> method. In fact, this vulnerability is extended even further with the introduction of nested mass assignment (and nested object forms) in Rails 2.3. The +accepts_nested_attributes_for+ declaration provides us the ability to extend mass assignment to model associations (+has_many+, +has_one+, +has_and_belongs_to_many+). For example:
+Note that this vulnerability is not restricted to database columns. Any setter method, unless explicitly protected, is accessible via the <tt>attributes=</tt> method. In fact, this vulnerability is extended even further with the introduction of nested mass assignment (and nested object forms) in Rails 2.3. The +accepts_nested_attributes_for+ declaration provides us the ability to extend mass assignment to model associations (+has_many+, +has_one+, +has_and_belongs_to_many+). For example:
<ruby>
class Person < ActiveRecord::Base
@@ -418,10 +410,17 @@ To avoid this, Rails provides two class methods in your Active Record class to c
attr_protected :admin
</ruby>
++attr_protected+ also optionally takes a scope option using :as which allows you to define multiple mass-assignment groupings. If no scope is defined then attributes will be added to the default group.
+
+<ruby>
+attr_protected :last_login, :as => :admin
+</ruby>
+
A much better way, because it follows the whitelist-principle, is the +attr_accessible+ method. It is the exact opposite of +attr_protected+, because _(highlight)it takes a list of attributes that will be accessible_. All other attributes will be protected. This way you won't forget to protect attributes when adding new ones in the course of development. Here is an example:
<ruby>
attr_accessible :name
+attr_accessible :name, :is_admin, :as => :admin
</ruby>
If you want to set a protected attribute, you will to have to assign it individually:
@@ -434,13 +433,43 @@ params[:user] # => {:name => "ow3ned", :admin => true}
@user.admin # => true
</ruby>
-A more paranoid technique to protect your whole project would be to enforce that all models whitelist their accessible attributes. This can be easily achieved with a very simple initializer:
+When assigning attributes in Active Record using +attributes=+, or +update_attributes+ the :default scope will be used. To assign attributes using different scopes you should use +assign_attributes+ which accepts an optional :as options parameter. If no :as option is provided then the :default scope will be used. You can also bypass mass-assignment security by using the +:without_protection+ option. Here is an example:
+
+<ruby>
+@user = User.new
+
+@user.assign_attributes({ :name => 'Josh', :is_admin => true })
+@user.name # => Josh
+@user.is_admin # => false
+
+@user.assign_attributes({ :name => 'Josh', :is_admin => true }, :as => :admin)
+@user.name # => Josh
+@user.is_admin # => true
+
+@user.assign_attributes({ :name => 'Josh', :is_admin => true }, :without_protection => true)
+@user.name # => Josh
+@user.is_admin # => true
+</ruby>
+
+In a similar way, +new+, +create+ and <tt>create!</tt> methods respect mass-assignment security and accepts either +:as+ or +:without_protection+ options. For example:
+
+<ruby>
+@user = User.new({ :name => 'Sebastian', :is_admin => true }, :as => :admin)
+@user.name # => Sebastian
+@user.is_admin # => true
+
+@user = User.create({ :name => 'Sebastian', :is_admin => true }, :without_protection => true)
+@user.name # => Sebastian
+@user.is_admin # => true
+</ruby>
+
+A more paranoid technique to protect your whole project would be to enforce that all models define their accessible attributes. This can be easily achieved with a very simple application config option of:
<ruby>
-ActiveRecord::Base.send(:attr_accessible, nil)
+config.active_record.whitelist_attributes = true
</ruby>
-This will create an empty whitelist of attributes available for mass assignment for all models in your app. As such, your models will need to explicitly whitelist accessible parameters by using an +attr_accessible+ declaration. This technique is best applied at the start of a new project. However, for an existing project with a thorough set of functional tests, it should be straightforward and relatively quick to insert this initializer, run your tests, and expose each attribute (via +attr_accessible+) as dictated by your failing tests.
+This will create an empty whitelist of attributes available for mass-assignment for all models in your app. As such, your models will need to explicitly whitelist or blacklist accessible parameters by using an +attr_accessible+ or +attr_protected+ declaration. This technique is best applied at the start of a new project. However, for an existing project with a thorough set of functional tests, it should be straightforward and relatively quick to use this application config option; run your tests, and expose each attribute (via +attr_accessible+ or +attr_protected+) as dictated by your failing tests.
h3. User Management
@@ -893,12 +922,6 @@ h4. Ajax Injection
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.
-h4. RJS Injection
-
--- _Don't forget to escape in JavaScript (RJS) templates, too._
-
-The RJS API generates blocks of JavaScript code based on Ruby code, thus allowing you to manipulate a view or parts of a view from the server side. <em class="highlight">If you allow user input in RJS templates, do escape it using +escape_javascript()+ within JavaScript functions, and in HTML parts using +h()+</em>. Otherwise an attacker could execute arbitrary JavaScript.
-
h4. Command Line Injection
-- _Use user-supplied command line parameters with caution._
diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile
index d3f72509c6..efa2bbdca6 100644
--- a/railties/guides/source/testing.textile
+++ b/railties/guides/source/testing.textile
@@ -79,9 +79,9 @@ steve:
Each fixture is given a name followed by an indented list of colon-separated key/value pairs. Records are separated by a blank space. You can place comments in a fixture file by using the # character in the first column.
-h5. ERb'in It Up
+h5. ERB'in It Up
-ERb allows you to embed ruby code within templates. Both the YAML and CSV fixture formats are pre-processed with ERb when you load fixtures. This allows you to use Ruby to help you generate some sample data.
+ERB allows you to embed ruby code within templates. Both the YAML and CSV fixture formats are pre-processed with ERB when you load fixtures. This allows you to use Ruby to help you generate some sample data.
<erb>
<% earth_size = 20 %>
@@ -391,7 +391,7 @@ There are a bunch of different types of assertions you can use. Here's the compl
|+assert_nil( obj, [msg] )+ |Ensures that +obj.nil?+ is true.|
|+assert_not_nil( obj, [msg] )+ |Ensures that +obj.nil?+ is false.|
|+assert_match( regexp, string, [msg] )+ |Ensures that a string matches the regular expression.|
-|+assert_no_match( regexp, string, [msg] )+ |Ensures that a string doesn't matches the regular expression.|
+|+assert_no_match( regexp, string, [msg] )+ |Ensures that a string doesn't match the regular expression.|
|+assert_in_delta( expecting, actual, delta, [msg] )+ |Ensures that the numbers +expecting+ and +actual+ are within +delta+ of each other.|
|+assert_throws( symbol, [msg] ) { block }+ |Ensures that the given block throws the symbol.|
|+assert_raise( exception1, exception2, ... ) { block }+ |Ensures that the given block raises one of the given exceptions.|
@@ -415,8 +415,8 @@ NOTE: +assert_valid(record)+ has been deprecated. Please use +assert(record.vali
|_.Assertion |_.Purpose|
|+assert_valid(record)+ |Ensures that the passed record is valid by Active Record standards and returns any error messages if it is not.|
-|+assert_difference(expressions, difference = 1, message = nil) {...}+ |Test numeric difference between the return value of an expression as a result of what is evaluated in the yielded block.|
-|+assert_no_difference(expressions, message = nil, &amp;block)+ |Asserts that the numeric result of evaluating an expression is not changed before and after invoking the passed in block.|
+|+assert_difference(expressions, difference = 1, message = nil) {...}+ |Test numeric difference between the return value of an expression as a result of what is evaluated in the yielded block.|
+|+assert_no_difference(expressions, message = nil, &amp;block)+ |Asserts that the numeric result of evaluating an expression is not changed before and after invoking the passed in block.|
|+assert_recognizes(expected_options, path, extras={}, message=nil)+ |Asserts that the routing of the given path was handled correctly and that the parsed options (given in the expected_options hash) match path. Basically, it asserts that Rails recognizes the route given by expected_options.|
|+assert_generates(expected_path, options, defaults={}, extras = {}, message=nil)+ |Asserts that the provided options can be used to generate the provided path. This is the inverse of assert_recognizes. The extras parameter is used to tell the request the names and values of additional request parameters that would be in a query string. The message parameter allows you to specify a custom error message for assertion failures.|
|+assert_response(type, message = nil)+ |Asserts that the response comes with a specific status code. You can specify +:success+ to indicate 200, +:redirect+ to indicate 300-399, +:missing+ to indicate 404, or +:error+ to match the 500-599 range|
@@ -592,7 +592,6 @@ There are more assertions that are primarily used in testing views:
|_.Assertion |_.Purpose|
|+assert_select_email+ |Allows you to make assertions on the body of an e-mail. |
-|+assert_select_rjs+ |Allows you to make assertions on an RJS response. +assert_select_rjs+ has variants which allow you to narrow down on the updated element or even a particular operation on an element.|
|+assert_select_encoded+ |Allows you to make assertions on encoded HTML. It does this by un-encoding the contents of each element and then calling the block with all the un-encoded elements.|
|+css_select(selector)+ or +css_select(element, selector)+ |Returns an array of all the elements selected by the _selector_. In the second variant it first matches the base _element_ and tries to match the _selector_ expression on any of its children. If there are no matches both variants return an empty array.|
@@ -748,7 +747,8 @@ You don't need to set up and run your tests by hand on a test-by-test basis. Rai
h3. 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+ that it is how we can use all the basic assertions in our tests.
+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/
@@ -941,7 +941,7 @@ h3. 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, as replacement for fixtures.
+* "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://rspec.info/, a behavior-driven development framework