Merge branch 'master' of github.com:lifo/docrails

This commit is contained in:
Vijay Dev 2012-05-01 19:06:03 +05:30
commit 42ff22f33a
30 changed files with 178 additions and 505 deletions

View File

@ -22,12 +22,12 @@ the email.
This can be as simple as:
class Notifier < ActionMailer::Base
delivers_from 'system@loudthinking.com'
default from: 'system@loudthinking.com'
def welcome(recipient)
@recipient = recipient
mail(:to => recipient,
:subject => "[Signed up] Welcome #{recipient}")
mail(to: recipient,
subject: "[Signed up] Welcome #{recipient}")
end
end

View File

@ -14,7 +14,7 @@ module ActionController #:nodoc:
protected
# Sends the file. This uses a server-appropriate method (such as X-Sendfile)
# via the Rack::Sendfile middleware. The header to use is set via
# config.action_dispatch.x_sendfile_header.
# +config.action_dispatch.x_sendfile_header+.
# Your server can also configure this for you by setting the X-Sendfile-Type header.
#
# Be careful to sanitize the path parameter if it is coming from a web

View File

@ -48,7 +48,7 @@ module ActionController
# method attribute_names.
#
# If you're going to pass the parameters to an +ActiveModel+ object (such as
# +User.new(params[:user])+), you might consider passing the model class to
# <tt>User.new(params[:user])</tt>), you might consider passing the model class to
# the method instead. The +ParamsWrapper+ will actually try to determine the
# list of attribute names from the model and only wrap those attributes:
#

View File

@ -179,11 +179,11 @@ module Mime
end
end
# input: 'text'
# returned value: [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT]
# For an input of <tt>'text'</tt>, returns <tt>[Mime::JSON, Mime::XML, Mime::ICS,
# Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT]</tt>.
#
# input: 'application'
# returned value: [Mime::HTML, Mime::JS, Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::URL_ENCODED_FORM]
# For an input of <tt>'application'</tt>, returns <tt>[Mime::HTML, Mime::JS,
# Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::URL_ENCODED_FORM]</tt>.
def parse_data_with_trailing_star(input)
Mime::SET.select { |m| m =~ input }
end
@ -192,7 +192,7 @@ module Mime
#
# Usage:
#
# Mime::Type.unregister(:mobile)
# Mime::Type.unregister(:mobile)
def unregister(symbol)
symbol = symbol.to_s.upcase
mime = Mime.const_get(symbol)

View File

@ -227,7 +227,7 @@ module ActionDispatch
# cookie was tampered with by the user (or a 3rd party), an ActiveSupport::MessageVerifier::InvalidSignature exception will
# be raised.
#
# This jar requires that you set a suitable secret for the verification on your app's config.secret_token.
# This jar requires that you set a suitable secret for the verification on your app's +config.secret_token+.
#
# Example:
#

View File

@ -18,10 +18,10 @@ module ActionDispatch
# classes before they are unloaded.
#
# By default, ActionDispatch::Reloader is included in the middleware stack
# only in the development environment; specifically, when config.cache_classes
# only in the development environment; specifically, when +config.cache_classes+
# is false. Callbacks may be registered even when it is not included in the
# middleware stack, but are executed only when +ActionDispatch::Reloader.prepare!+
# or +ActionDispatch::Reloader.cleanup!+ are called manually.
# middleware stack, but are executed only when <tt>ActionDispatch::Reloader.prepare!</tt>
# or <tt>ActionDispatch::Reloader.cleanup!</tt> are called manually.
#
class Reloader
include ActiveSupport::Callbacks

View File

@ -43,16 +43,14 @@ module ActionDispatch
# edit_polymorphic_path(@post) # => "/posts/1/edit"
# polymorphic_path(@post, :format => :pdf) # => "/posts/1.pdf"
#
# == Using with mounted engines
# == Usage with mounted engines
#
# If you use mounted engine, there is a possibility that you will need to use
# polymorphic_url pointing at engine's routes. To do that, just pass proxy used
# to reach engine's routes as a first argument:
# If you are using a mounted engine and you need to use a polymorphic_url
# pointing at the engine's routes, pass in the engine's route proxy as the first
# argument to the method. For example:
#
# For example:
#
# polymorphic_url([blog, @post]) # it will call blog.post_path(@post)
# form_for([blog, @post]) # => "/blog/posts/1
# polymorphic_url([blog, @post]) # calls blog.post_path(@post)
# form_for([blog, @post]) # => "/blog/posts/1"
#
module PolymorphicRoutes
# Constructs a call to a named RESTful route for the given record and returns the

View File

@ -113,7 +113,7 @@ module ActionView
# == Caching multiple stylesheets into one
#
# You can also cache multiple stylesheets into one file, which requires less HTTP connections and can better be
# compressed by gzip (leading to faster transfers). Caching will only happen if config.perform_caching
# compressed by gzip (leading to faster transfers). Caching will only happen if +config.perform_caching+
# is set to true (which is the case by default for the Rails production environment, but not for the development
# environment). Examples:
#

View File

@ -83,6 +83,7 @@ module ActiveModel
# in-place attributes.
#
# person.name_will_change!
# person.name_change # => ['Bill', 'Bill']
# person.name << 'y'
# person.name_change # => ['Bill', 'Billy']
module Dirty

View File

@ -304,21 +304,22 @@ module ActiveRecord #:nodoc:
# (or a bad spelling of an existing one).
# * AssociationTypeMismatch - The object assigned to the association wasn't of the type
# specified in the association definition.
# * SerializationTypeMismatch - The serialized object wasn't of the class specified as the second parameter.
# * ConnectionNotEstablished - No connection has been established. Use <tt>establish_connection</tt>
# before querying.
# * RecordNotFound - No record responded to the +find+ method. Either the row with the given ID doesn't exist
# or the row didn't meet the additional restrictions. Some +find+ calls do not raise this exception to signal
# nothing was found, please check its documentation for further details.
# * StatementInvalid - The database server rejected the SQL statement. The precise error is added in the message.
# * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the
# <tt>attributes=</tt> method. The +errors+ property of this exception contains an array of
# AttributeAssignmentError
# objects that should be inspected to determine which attributes triggered the errors.
# * AttributeAssignmentError - An error occurred while doing a mass assignment through the
# <tt>attributes=</tt> method.
# You can inspect the +attribute+ property of the exception object to determine which attribute
# triggered the error.
# * ConnectionNotEstablished - No connection has been established. Use <tt>establish_connection</tt>
# before querying.
# * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the
# <tt>attributes=</tt> method. The +errors+ property of this exception contains an array of
# AttributeAssignmentError
# objects that should be inspected to determine which attributes triggered the errors.
# * RecordInvalid - raised by save! and create! when the record is invalid
# * RecordNotFound - No record responded to the +find+ method. Either the row with the given ID doesn't exist
# or the row didn't meet the additional restrictions. Some +find+ calls do not raise this exception to signal
# nothing was found, please check its documentation for further details.
# * SerializationTypeMismatch - The serialized object wasn't of the class specified as the second parameter.
# * StatementInvalid - The database server rejected the SQL statement. The precise error is added in the message.
#
# *Note*: The attributes listed are class-level attributes (accessible from both the class and instance level).
# So it's possible to assign a logger to the class through <tt>Base.logger=</tt> which will then be used by all

View File

@ -70,7 +70,7 @@ module ActiveRecord
# the threshold is set to 0.
#
# As the name of the method suggests this only applies to automatic
# EXPLAINs, manual calls to +ActiveRecord::Relation#explain+ run.
# EXPLAINs, manual calls to <tt>ActiveRecord::Relation#explain</tt> run.
def silence_auto_explain
current = Thread.current
original, current[:available_queries_for_explain] = current[:available_queries_for_explain], false

View File

@ -18,7 +18,7 @@ class Hash
end
# Replaces the hash with only the given keys.
# Returns a hash contained the removed key/value pairs
# Returns a hash containing the removed key/value pairs.
# {:a => 1, :b => 2, :c => 3, :d => 4}.slice!(:a, :b) # => {:c => 3, :d => 4}
def slice!(*keys)
keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)

View File

@ -11,7 +11,21 @@ module ActiveSupport
@behavior ||= [DEFAULT_BEHAVIORS[:stderr]]
end
# Sets the behavior to the specified value. Can be a single value or an array.
# Sets the behavior to the specified value. Can be a single value, array, or
# and object that responds to +call+.
#
# Available options:
#
# [+stderr+] Log all deprecation warnings to $stderr
# [+log+] Log all deprecation warnins to +Rails.logger+
# [+notify] Use +ActiveSupport::Notifications+ to notify of +deprecation.rails+.
# [+silence+] Do nothing
#
# Note, setting behaviors only effects deprecations that happen afterwards.
# For example, All gems are required before Rails boots. Those gems may
# raise deprecation warnings according to the default setting. Setting
# behavior in a config file only effects code after boot time. So, the
# set behavior applies to deprecations raised at runtime.
#
# Available behaviors:
#
@ -24,6 +38,10 @@ module ActiveSupport
#
# ActiveSupport::Deprecation.behavior = :stderr
# ActiveSupport::Deprecation.behavior = [:stderr, :log]
# ActiveSupport::Deprecation.behavior = proc { |message, callstack|
# # custom stuff
# }
# ActiveSupport::Deprecation.behavior = MyCustomHandler
def behavior=(behavior)
@behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || b }
end

View File

@ -106,7 +106,7 @@ module ActiveSupport
# a nicer looking title. +titleize+ is meant for creating pretty output. It is not
# used in the Rails internals.
#
# +titleize+ is also aliased as as +titlecase+.
# +titleize+ is also aliased as +titlecase+.
#
# Examples:
# "man from the boondocks".titleize # => "Man From The Boondocks"

View File

@ -48,6 +48,7 @@ module ActiveSupport
# end
# end
#
# Exceptions raised inside exception handlers are not propagated up.
def rescue_from(*klasses, &block)
options = klasses.extract_options!

View File

@ -204,6 +204,7 @@ module ActiveSupport
@current_period = nil
end
# Returns the offset of this time zone in seconds.
def utc_offset
if @utc_offset
@utc_offset

View File

@ -10,12 +10,12 @@
</div>
<% end %>
<p>
<%= f.label :title %><br>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>
<p>
<%= f.label :text %><br>
<%= f.label :text %><br />
<%= f.text_area :text %>
</p>

View File

@ -8,5 +8,21 @@
<%= @post.text %>
</p>
<%= link_to 'Back', :action => :index %>
| <%= link_to 'Edit', :action => :edit, :id => @post.id %>
<h2>Add a comment:</h2>
<%= form_for([@post, @post.comments.build]) do |f| %>
<p>
<%= f.label :commenter %><br />
<%= f.text_field :commenter %>
</p>
<p>
<%= f.label :body %><br />
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<%= link_to 'Edit Post', edit_post_path(@post) %> |
<%= link_to 'Back to Posts', posts_path %>

View File

@ -1,15 +1,8 @@
Blog::Application.routes.draw do
# resources :posts do
# resources :comments
# end
get "posts" => "posts#index"
get "posts/new"
post "posts/create"
get "posts/:id" => "posts#show", :as => :post
get "posts/:id/edit" => "posts#edit"
put "posts/:id" => "posts#update"
delete "posts/:id" => "posts#destroy"
resources :posts do
resources :comments
end
# The priority is based upon order of creation:
# first created -> highest priority.

View File

@ -1,9 +0,0 @@
# Read about fixtures at http://api.rubyonrails.org/classes/Fixtures.html
one:
name: MyString
post:
two:
name: MyString
post:

View File

@ -4,7 +4,7 @@ This guide should provide you with all you need to get started in sending and re
endprologue.
WARNING. This Guide is based on Rails 3.0. Some of the code shown here will not work in earlier versions of Rails.
WARNING. This Guide is based on Rails 3.2. Some of the code shown here will not work in earlier versions of Rails.
h3. Introduction

View File

@ -910,7 +910,7 @@ This code looks fine at the first sight. But the problem lies within the total n
Active Record lets you specify in advance all the associations that are going to be loaded. This is possible by specifying the +includes+ method of the +Model.find+ call. With +includes+, Active Record ensures that all of the specified associations are loaded using the minimum possible number of queries.
Revisiting the above case, we could rewrite +Client.all+ to use eager load addresses:
Revisiting the above case, we could rewrite +Client.limit(10)+ to use eager load addresses:
<ruby>
clients = Client.includes(:address).limit(10)

View File

@ -157,7 +157,7 @@ and you can expire it using the +expire_fragment+ method, like so:
expire_fragment(:controller => 'products', :action => 'recent', :action_suffix => 'all_products')
</ruby>
If you don't want the cache block to bind to the action that called it, You can also use globally keyed fragments by calling the +cache+ method with a key, like so:
If you don't want the cache block to bind to the action that called it, you can also use globally keyed fragments by calling the +cache+ method with a key:
<ruby>
<% cache('all_available_products') do %>

View File

@ -105,6 +105,13 @@ $ cd railties
$ TEST_DIR=generators bundle exec rake test
</shell>
You can run any single test separately too:
<shell>
$ cd actionpack
$ ruby -Itest test/template/form_helper_test.rb
</shell>
h4. Warnings
The test suite runs with warnings enabled. Ideally, Ruby on Rails should issue no warnings, but there may be a few, as well as some from third-party libraries. Please ignore (or fix!) them, if any, and submit patches that do not issue new warnings.
@ -201,6 +208,12 @@ $ bundle exec rake test
will now run the four of them in turn.
You can also run any single test separately:
<shell>
$ ARCONN=sqlite3 ruby -Itest test/cases/associations/has_many_associations_test.rb
</shell>
You can invoke +test_jdbcmysql+, +test_jdbcsqlite3+ or +test_jdbcpostgresql+ also. See the file +activerecord/RUNNING_UNIT_TESTS+ for information on running more targeted database tests, or the file +ci/travis.rb+ for the test suite run by the continuous integration server.
h4. Older Versions of Ruby on Rails

View File

@ -72,7 +72,8 @@ step needed to make this example application has been left out, so you can
literally follow along step by step. You can get the complete code
"here":https://github.com/lifo/docrails/tree/master/guides/code/getting_started.
By following along with this guide, you'll create a Rails project called <tt>blog</tt>, a
By following along with this guide, you'll create a Rails project called
+blog+, a
(very) simple weblog. Before you can start building the application, you need to
make sure that you have Rails itself installed.
@ -108,7 +109,8 @@ $ rails new blog
This will create a Rails application called Blog in a directory called blog.
TIP: You can see all of the command line options that the Rails application builder accepts by running <tt>rails new -h</tt>.
TIP: You can see all of the command line options that the Rails
application builder accepts by running +rails new -h+.
After you create the blog application, switch to its folder to continue work directly in that application:
@ -116,7 +118,10 @@ After you create the blog application, switch to its folder to continue work dir
$ cd blog
</shell>
The +rails new blog+ command we ran above created a folder in your working directory called <tt>blog</tt>. The <tt>blog</tt> directory has a number of auto-generated files and folders that make up the structure of a Rails application. Most of the work in this tutorial will happen in the <tt>app/</tt> folder, but here's a basic rundown on the function of each of the files and folders that Rails created by default:
The +rails new blog+ command we ran above created a folder in your
working directory called +blog+. The +blog+ directory has a number of
auto-generated files and folders that make up the structure of a Rails
application. Most of the work in this tutorial will happen in the +app/+ folder, but here's a basic rundown on the function of each of the files and folders that Rails created by default:
|_.File/Folder|_.Purpose|
|app/|Contains the controllers, models, views, helpers, mailers and assets for your application. You'll focus on this folder for the remainder of this guide.|
@ -385,11 +390,10 @@ This action is now displaying the parameters for the post that are coming in fro
h4. Creating the Post model
Rails uses models to manage database objects, so if you want to save
data to the database you'll have to create a model. In our blog
application you want to save posts, so you'll create a +Post+ model.
You can create a model with the following command:
Models in Rails use a singular name, and their corresponding database tables use
a plural name. Rails provides a generator for creating models, which
most Rails developers tend to use when creating new models.
To create the new model, run this command in your terminal:
<shell>
$ rails generate model Post title:string text:text
@ -457,7 +461,7 @@ NOTE. Because you're working in the development environment by default, this
command will apply to the database defined in the +development+ section of your
+config/database.yml+ file. If you would like to execute migrations in another
environment, for instance in production, you must explicitly pass it when
invoking the command: <tt>rake db:migrate RAILS_ENV=production</tt>.
invoking the command: +rake db:migrate RAILS_ENV=production+.
h4. Saving data in the controller
@ -1095,424 +1099,65 @@ posts. In the next section will see how Rails can aid us when creating
REST applications, and how we can refactor our Blog app to take
advantage of it.
h4. Using the Console
h4. Going Deeper into REST
To see your validations in action, you can use the console. The console is a
command-line tool that lets you execute Ruby code in the context of your
application:
We've now covered all the CRUD actions of a REST app. We did so by
declaring separate routes with the appropriate verbs into
+config/routes.rb+. Here's how that file looks so far:
<ruby>
get "posts" => "posts#index"
get "posts/new"
post "posts/create"
get "posts/:id" => "posts#show", :as => :post
get "posts/:id/edit" => "posts#edit"
put "posts/:id" => "posts#update"
delete "posts/:id" => "posts#destroy"
</ruby>
That's a lot to type for covering a single *resource*. Fortunately,
Rails provides a +resources+ method which can be used to declare a
standard REST resource. Here's how +config/routes/rb+ looks after the
cleanup:
<ruby>
Blog::Application.routes.draw do
resources :posts
root :to => "welcome#index"
end
</ruby>
If you run +rake routes+, you'll see that all the routes that we
declared before are still available, and the app still works as before.
<shell>
$ rails console
# rake routes
posts GET /posts(.:format) posts#index
POST /posts(.:format) posts#create
new_post GET /posts/new(.:format) posts#new
edit_post GET /posts/:id/edit(.:format) posts#edit
post GET /posts/:id(.:format) posts#show
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy
root / welcome#index
</shell>
TIP: The default console will make changes to your database. You can instead
open a console that will roll back any changes you make by using <tt>rails console
--sandbox</tt>.
After the console loads, you can use it to work with your application's models:
<shell>
>> p = Post.new(:content => "A new post")
=> #<Post id: nil, name: nil, title: nil,
content: "A new post", created_at: nil,
updated_at: nil>
>> p.save
=> false
>> p.errors.full_messages
=> ["Name can't be blank", "Title can't be blank", "Title is too short (minimum is 5 characters)"]
</shell>
This code shows creating a new +Post+ instance, attempting to save it and
getting +false+ for a return value (indicating that the save failed), and
inspecting the +errors+ of the post.
When you're finished, type +exit+ and hit +return+ to exit the console.
TIP: Unlike the development web server, the console does not automatically load
your code afresh for each line. If you make changes to your models (in your editor)
while the console is open, type +reload!+ at the console prompt to load them.
h4. Listing All Posts
Let's dive into the Rails code a little deeper to see how the application is
showing us the list of Posts. Open the file
+app/controllers/posts_controller.rb+ and look at the
+index+ action:
<ruby>
def index
@posts = Post.all
respond_to do |format|
format.html # index.html.erb
format.json { render :json => @posts }
end
end
</ruby>
+Post.all+ returns all of the posts currently in the database as an array
of +Post+ records that we store in an instance variable called +@posts+.
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 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>
<table>
<tr>
<th>Name</th>
<th>Title</th>
<th>Content</th>
<th></th>
<th></th>
<th></th>
</tr>
<% @posts.each do |post| %>
<tr>
<td><%= post.name %></td>
<td><%= post.title %></td>
<td><%= post.content %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, :confirm => 'Are you sure?',
:method => :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New post', new_post_path %>
</erb>
This view iterates over the contents of the +@posts+ array to display content
and links. A few things to note in the view:
* +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 and above, this is now the default. To get unescaped HTML, you now use <tt>&lt;%= raw post.name %&gt;</tt>.
TIP: For more details on the rendering process, see "Layouts and Rendering in
Rails":layouts_and_rendering.html.
h4. Customizing the Layout
The view is only part of the story of how HTML is displayed in your web browser.
Rails also has the concept of +layouts+, which are containers for views. When
Rails renders a view to the browser, it does so by putting the view's HTML into
a layout's HTML. In previous versions of Rails, the +rails generate scaffold+
command would automatically create a controller specific layout, like
+app/views/layouts/posts.html.erb+, for the posts controller. However this has
been changed in Rails 3. An application specific +layout+ is used for all the
controllers and can be found in +app/views/layouts/application.html.erb+. Open
this layout in your editor and modify the +body+ tag to include the style directive
below:
<erb>
<!DOCTYPE html>
<html>
<head>
<title>Blog</title>
<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
</head>
<body style="background-color: #EEEEEE;">
<%= yield %>
</body>
</html>
</erb>
Now when you refresh the +/posts+ page, you'll see a gray background to the
page. This same gray background will be used throughout all the views.
h4. Creating New Posts
Creating a new post involves two actions. The first is the +new+ action, which
instantiates an empty +Post+ object:
<ruby>
def new
@post = Post.new
respond_to do |format|
format.html # new.html.erb
format.json { render :json => @post }
end
end
</ruby>
The +new.html.erb+ view displays this empty Post to the user:
<erb>
<h1>New post</h1>
<%= render 'form' %>
<%= 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 the form used to edit a post, both having text fields for the name and
title, a text area for the content, and a button to create the new post or to update
the existing one.
If you take a look at +views/posts/_form.html.erb+ file, you will see the
following:
<erb>
<%= form_for(@post) do |f| %>
<% if @post.errors.any? %>
<div id="errorExplanation">
<h2><%= pluralize(@post.errors.count, "error") %> prohibited
this post from being saved:</h2>
<ul>
<% @post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :content %><br />
<%= f.text_area :content %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
</erb>
This partial receives all the instance variables defined in the calling view
file. In this case, the controller assigned the new +Post+ object to +@post+,
which will thus be available in both the view and the partial as +@post+.
For more information on partials, refer to the "Layouts and Rendering in
Rails":layouts_and_rendering.html#using-partials guide.
The +form_for+ block is used to create an HTML form. Within this block, you have
access to methods to build various controls on the form. For example,
+f.text_field :name+ tells Rails to create a text input on the form and to hook
it up to the +name+ attribute of the instance being displayed. You can only use
these methods with attributes of the model that the form is based on (in this
case +name+, +title+, and +content+). Rails uses +form_for+ in preference to
having you write raw HTML because the code is more succinct, and because it
explicitly ties the form to a particular model instance.
The +form_for+ block is also smart enough to work out if you are doing a _New
Post_ or an _Edit Post_ action, and will set the form +action+ tags and submit
button names appropriately in the HTML output.
TIP: If you need to create an HTML form that displays arbitrary fields, not tied
to a model, you should use the +form_tag+ method, which provides shortcuts for
building forms that are not necessarily tied to a model instance.
When the user clicks the +Create Post+ button on this form, the browser will
send information back to the +create+ action of the controller (Rails knows to
call the +create+ action because the form is sent with an HTTP POST request;
that's one of the conventions that were mentioned earlier):
<ruby>
def create
@post = Post.new(params[:post])
respond_to do |format|
if @post.save
format.html { redirect_to(@post,
:notice => 'Post was successfully created.') }
format.json { render :json => @post,
:status => :created, :location => @post }
else
format.html { render :action => "new" }
format.json { render :json => @post.errors,
:status => :unprocessable_entity }
end
end
end
</ruby>
The +create+ action instantiates a new Post object from the data supplied by the
user on the form, which Rails makes available in the +params+ hash. After
successfully saving the new post, +create+ returns the appropriate format that
the user has requested (HTML in our case). It then redirects the user to the
resulting post +show+ action and sets a notice to the user that the Post was
successfully created.
If the post was not successfully saved, due to a validation error, then the
controller returns the user back to the +new+ action with any error messages so
that the user has the chance to fix the error and try again.
The "Post was successfully created." message is stored in the Rails
+flash+ hash (usually just called _the flash_), so that messages can be carried
over to another action, providing the user with useful information on the status
of their request. In the case of +create+, the user never actually sees any page
rendered during the post creation process, because it immediately redirects to
the new +Post+ as soon as Rails saves the record. The Flash carries over a message to
the next action, so that when the user is redirected back to the +show+ action,
they are presented with a message saying "Post was successfully created."
h4. Showing an Individual Post
When you click the +show+ link for a post on the index page, it will bring you
to a URL like +http://localhost:3000/posts/1+. Rails interprets this as a call
to the +show+ action for the resource, and passes in +1+ as the +:id+ parameter.
Here's the +show+ action:
<ruby>
def show
@post = Post.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render :json => @post }
end
end
</ruby>
The +show+ action uses +Post.find+ to search for a single record in the database
by its id value. After finding the record, Rails displays it by using
+app/views/posts/show.html.erb+:
<erb>
<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
<%= @post.name %>
</p>
<p>
<b>Title:</b>
<%= @post.title %>
</p>
<p>
<b>Content:</b>
<%= @post.content %>
</p>
<%= link_to 'Edit', edit_post_path(@post) %> |
<%= link_to 'Back', posts_path %>
</erb>
h4. Editing Posts
Like creating a new post, editing a post is a two-part process. The first step
is a request to +edit_post_path(@post)+ with a particular post. This calls the
+edit+ action in the controller:
<ruby>
def edit
@post = Post.find(params[:id])
end
</ruby>
After finding the requested post, Rails uses the +edit.html.erb+ view to display
it:
<erb>
<h1>Editing post</h1>
<%= render 'form' %>
<%= link_to 'Show', @post %> |
<%= link_to 'Back', posts_path %>
</erb>
Again, as with the +new+ action, the +edit+ action is using the +form+ partial.
This time, however, the form will do a PUT action to the +PostsController+ and the
submit button will display "Update Post".
Submitting the form created by this view will invoke the +update+ action within
the controller:
<ruby>
def update
@post = Post.find(params[:id])
respond_to do |format|
if @post.update_attributes(params[:post])
format.html { redirect_to(@post,
:notice => 'Post was successfully updated.') }
format.json { head :no_content }
else
format.html { render :action => "edit" }
format.json { render :json => @post.errors,
:status => :unprocessable_entity }
end
end
end
</ruby>
In the +update+ action, Rails first uses the +:id+ parameter passed back from
the edit view to locate the database record that's being edited. The
+update_attributes+ call then takes the +post+ parameter (a hash) from the request
and applies it to this record. If all goes well, the user is redirected to the
post's +show+ action. If there are any problems, it redirects back to the +edit+ action to
correct them.
h4. Destroying a Post
Finally, clicking one of the +destroy+ links sends the associated id to the
+destroy+ action:
<ruby>
def destroy
@post = Post.find(params[:id])
@post.destroy
respond_to do |format|
format.html { redirect_to posts_url }
format.json { head :no_content }
end
end
</ruby>
The +destroy+ method of an Active Record model instance removes the
corresponding record from the database. After that's done, there isn't any
record to display, so Rails redirects the user's browser to the index action of
the controller.
TIP: In general, Rails encourages the use of resources objects in place
of declaring routes manually. For more information about routing, see
"Rails Routing from the Outside In":routing.html.
h3. Adding a Second Model
Now that you've seen what a model built with scaffolding looks like, it's time to
add a second model to the application. The second model will handle comments on
It's time to add a second model to the application. The second model will handle comments on
blog posts.
h4. Generating a Model
Models in Rails use a singular name, and their corresponding database tables use
a plural name. For the model to hold comments, the convention is to use the name
+Comment+. Even if you don't want to use the entire apparatus set up by
scaffolding, most Rails developers still use generators to make things like
models and controllers. To create the new model, run this command in your
terminal:
We're going to se the same generator that we used before when creating
the +Post+ model. This time we'll create a +Comment+ model to hold
reference of post comments. Run this command in your terminal:
<shell>
$ rails generate model Comment commenter:string body:text post:references
@ -1600,7 +1245,6 @@ You'll need to edit the +post.rb+ file to add the other side of the association:
<ruby>
class Post < ActiveRecord::Base
validates :name, :presence => true
validates :title, :presence => true,
:length => { :minimum => 5 }
@ -1619,9 +1263,7 @@ h4. Adding a Route for Comments
As with the +welcome+ 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. Near the top, you will see the entry for +posts+
that was added automatically by the scaffold generator: <tt>resources
:posts</tt>. Edit it as follows:
+config/routes.rb+ file again, and edit it as follows:
<ruby>
resources :posts do
@ -1639,7 +1281,7 @@ In":routing.html guide.
h4. Generating a Controller
With the model in hand, you can turn your attention to creating a matching
controller. Again, there's a generator for this:
controller. Again, we'll use the same generator we used before:
<shell>
$ rails generate controller Comments
@ -1666,40 +1308,33 @@ So first, we'll wire up the Post show template
(+/app/views/posts/show.html.erb+) to let us make a new comment:
<erb>
<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
<%= @post.name %>
</p>
<p>
<b>Title:</b>
<strong>Title:</strong>
<%= @post.title %>
</p>
<p>
<b>Content:</b>
<%= @post.content %>
<strong>Text:</strong>
<%= @post.texthttp://beginningruby.org/ %>
</p>
<h2>Add a comment:</h2>
<%= form_for([@post, @post.comments.build]) do |f| %>
<div class="field">
<p>
<%= f.label :commenter %><br />
<%= f.text_field :commenter %>
</div>
<div class="field">
</p>
<p>
<%= f.label :body %><br />
<%= f.text_area :body %>
</div>
<div class="actions">
</p>
<p>
<%= f.submit %>
</div>
</p>
<% end %>
<%= link_to 'Edit Post', edit_post_path(@post) %> |
<%= link_to 'Back to Posts', posts_path %> |
<%= link_to 'Back to Posts', posts_path %>
</erb>
This adds a form on the +Post+ show page that creates a new comment by
@ -2074,6 +1709,7 @@ class Post < ActiveRecord::Base
has_many :comments, :dependent => :destroy
has_many :tags
attr_protected :tags
accepts_nested_attributes_for :tags, :allow_destroy => :true,
:reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } }

View File

@ -837,7 +837,7 @@ If you have a large route file that you would like to break up into multiple fil
draw :admin
</ruby>
Then, create a file called +config/routes/admin.rb+. Name the file the same as the symbol passed to the +draw+ method). You can then use the normal routing DSL inside that file:
Then, create a file called +config/routes/admin.rb+. Name the file the same as the symbol passed to the +draw+ method. You can then use the normal routing DSL inside that file:
<ruby>
# in config/routes/admin.rb

View File

@ -38,6 +38,10 @@ h4(#identity_map4_0). IdentityMap
Rails 4.0 has removed <tt>IdentityMap</tt> from <tt>ActiveRecord</tt>, due to "some inconsistencies with associations":https://github.com/rails/rails/commit/302c912bf6bcd0fa200d964ec2dc4a44abe328a6. If you have manually enabled it in your application, you will have to remove the following config that has no effect anymore: <tt>config.active_record.identity_map</tt>.
h4(#active_model4_0). ActiveModel
Rails 4.0 has changed how errors attach with the ConfirmationValidator. Now when confirmation validations fail the error will be attached to <tt>:#{attribute}_confirmation</tt> instead of <tt>attribute</tt>.
h3. Upgrading from Rails 3.1 to Rails 3.2
If your application is currently on any version of Rails older than 3.1.x, you should upgrade to Rails 3.1 before attempting an update to Rails 3.2.

View File

@ -332,7 +332,7 @@ module Rails
#
# == Loading priority
#
# In order to change engine's priority you can use config.railties_order in main application.
# In order to change engine's priority you can use +config.railties_order+ in main application.
# It will affect the priority of loading views, helpers, assets and all the other files
# related to engine or application.
#

View File

@ -22,7 +22,7 @@ module Rails
#
# * creating initializers
# * configuring a Rails framework for the application, like setting a generator
# * adding config.* keys to the environment
# * +adding config.*+ keys to the environment
# * setting up a subscriber with ActiveSupport::Notifications
# * adding rake tasks
#

View File

@ -43,7 +43,7 @@ module Rails
ActiveSupport.on_load(:before_configuration, :yield => true, &block)
end
# Third configurable block to run. Does not run if config.cache_classes
# Third configurable block to run. Does not run if +config.cache_classes+
# set to false.
def before_eager_load(&block)
ActiveSupport.on_load(:before_eager_load, :yield => true, &block)