mirror of https://github.com/rails/rails
Merge branch 'master' of github.com:lifo/docrails
This commit is contained in:
commit
42ff22f33a
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
#
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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!
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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 %>
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
# Read about fixtures at http://api.rubyonrails.org/classes/Fixtures.html
|
||||
|
||||
one:
|
||||
name: MyString
|
||||
post:
|
||||
|
||||
two:
|
||||
name: MyString
|
||||
post:
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 %>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 +<%=h post.name %>+ 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><%= raw post.name %></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 +<%= render 'form' %>+ 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? } }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
#
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue