aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionmailer/lib/action_mailer/base.rb4
-rw-r--r--actionpack/lib/action_controller/metal/params_wrapper.rb2
-rw-r--r--actionpack/lib/action_controller/metal/streaming.rb6
-rw-r--r--activemodel/lib/active_model/serialization.rb2
-rw-r--r--activemodel/lib/active_model/validations.rb17
-rw-r--r--activemodel/lib/active_model/validations/with.rb6
-rw-r--r--guides/assets/images/getting_started/confirm_dialog.pngbin0 -> 36070 bytes
-rw-r--r--guides/assets/images/getting_started/undefined_method_post_path.pngbin0 -> 15254 bytes
-rw-r--r--guides/code/getting_started/app/controllers/posts_controller.rb7
-rw-r--r--guides/code/getting_started/app/views/posts/_form.html.erb2
-rw-r--r--guides/code/getting_started/app/views/posts/index.html.erb2
-rw-r--r--guides/code/getting_started/config/routes.rb5
-rw-r--r--guides/source/active_record_validations_callbacks.textile2
-rw-r--r--guides/source/active_support_core_extensions.textile2
-rw-r--r--guides/source/engines.textile2
-rw-r--r--guides/source/generators.textile2
-rw-r--r--guides/source/getting_started.textile173
-rw-r--r--railties/lib/rails/configuration.rb2
-rw-r--r--railties/lib/rails/generators/test_case.rb8
-rw-r--r--railties/lib/rails/paths.rb2
20 files changed, 219 insertions, 27 deletions
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index c508512ff6..e24a7f52d5 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -486,7 +486,7 @@ module ActionMailer #:nodoc:
self.class.mailer_name
end
- # Allows you to pass random and unusual headers to the new +Mail::Message+ object
+ # Allows you to pass random and unusual headers to the new <tt>Mail::Message</tt> object
# which will add them to itself.
#
# headers['X-Special-Domain-Specific-Header'] = "SecretValue"
@@ -497,7 +497,7 @@ module ActionMailer #:nodoc:
# headers 'X-Special-Domain-Specific-Header' => "SecretValue",
# 'In-Reply-To' => incoming.message_id
#
- # The resulting Mail::Message will have the following in it's header:
+ # The resulting Mail::Message will have the following in its header:
#
# X-Special-Domain-Specific-Header: SecretValue
def headers(args=nil)
diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb
index fa760f2658..17e2db74d4 100644
--- a/actionpack/lib/action_controller/metal/params_wrapper.rb
+++ b/actionpack/lib/action_controller/metal/params_wrapper.rb
@@ -66,7 +66,7 @@ module ActionController
# class Admin::UsersController < ApplicationController
# end
#
- # will try to check if +Admin::User+ or +User+ model exists, and use it to
+ # will try to check if <tt>Admin::User</tt> or +User+ model exists, and use it to
# determine the wrapper key respectively. If both models don't exist,
# it will then fallback to use +user+ as the key.
module ParamsWrapper
diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb
index 52aaed0ed4..eeb37db2e7 100644
--- a/actionpack/lib/action_controller/metal/streaming.rb
+++ b/actionpack/lib/action_controller/metal/streaming.rb
@@ -139,17 +139,17 @@ module ActionController #:nodoc:
# session or flash after the template starts rendering will not propagate
# to the client.
#
- # If you try to modify cookies, session or flash, an +ActionDispatch::ClosedError+
+ # If you try to modify cookies, session or flash, an <tt>ActionDispatch::ClosedError</tt>
# will be raised, showing those objects are closed for modification.
#
# == Middlewares
#
# Middlewares that need to manipulate the body won't work with streaming.
# You should disable those middlewares whenever streaming in development
- # or production. For instance, +Rack::Bug+ won't work when streaming as it
+ # or production. For instance, <tt>Rack::Bug</tt> won't work when streaming as it
# needs to inject contents in the HTML body.
#
- # Also +Rack::Cache+ won't work with streaming as it does not support
+ # Also <tt>Rack::Cache</tt> won't work with streaming as it does not support
# streaming bodies yet. Whenever streaming Cache-Control is automatically
# set to "no-cache".
#
diff --git a/activemodel/lib/active_model/serialization.rb b/activemodel/lib/active_model/serialization.rb
index a5828476b1..4403ef060b 100644
--- a/activemodel/lib/active_model/serialization.rb
+++ b/activemodel/lib/active_model/serialization.rb
@@ -34,7 +34,7 @@ module ActiveModel
#
# Most of the time though, you will want to include the JSON or XML
# serializations. Both of these modules automatically include the
- # +ActiveModel::Serialization+ module, so there is no need to explicitly
+ # <tt>ActiveModel::Serialization</tt> module, so there is no need to explicitly
# include it.
#
# A minimal implementation including XML and JSON would be:
diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb
index 0e15155b85..3ed72bae3b 100644
--- a/activemodel/lib/active_model/validations.rb
+++ b/activemodel/lib/active_model/validations.rb
@@ -65,7 +65,7 @@ module ActiveModel
#
# attr_accessor :first_name, :last_name
#
- # validates_each :first_name, :last_name do |record, attr, value|
+ # validates_each :first_name, :last_name, :allow_blank => true do |record, attr, value|
# record.errors.add attr, 'starts with z.' if value.to_s[0] == ?z
# end
# end
@@ -128,6 +128,19 @@ module ActiveModel
# end
# end
#
+ # Options:
+ # * <tt>:on</tt> - Specifies the context where this validation is active
+ # (e.g. <tt>:on => :create</tt> or <tt>:on => :custom_validation_context</tt>)
+ # * <tt>:allow_nil</tt> - Skip validation if attribute is +nil+.
+ # * <tt>:allow_blank</tt> - Skip validation if attribute is blank.
+ # * <tt>:if</tt> - Specifies a method, proc or string to call to determine
+ # if the validation should occur (e.g. <tt>:if => :allow_validation</tt>,
+ # or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The method,
+ # proc or string should return or evaluate to a true or false value.
+ # * <tt>:unless</tt> - Specifies a method, proc or string to call to determine if the validation should
+ # not occur (e.g. <tt>:unless => :skip_validation</tt>, or
+ # <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
+ # method, proc or string should return or evaluate to a true or false value.
def validate(*args, &block)
options = args.extract_options!
if options.key?(:on)
@@ -145,7 +158,7 @@ module ActiveModel
_validators.values.flatten.uniq
end
- # List all validators that being used to validate a specific attribute.
+ # List all validators that are being used to validate a specific attribute.
def validators_on(*attributes)
attributes.map do |attribute|
_validators[attribute.to_sym]
diff --git a/activemodel/lib/active_model/validations/with.rb b/activemodel/lib/active_model/validations/with.rb
index 72b8562b93..991c5f7b82 100644
--- a/activemodel/lib/active_model/validations/with.rb
+++ b/activemodel/lib/active_model/validations/with.rb
@@ -126,12 +126,12 @@ module ActiveModel
# end
#
# Standard configuration options (:on, :if and :unless), which are
- # available on the class version of validates_with, should instead be
- # placed on the <tt>validates</tt> method as these are applied and tested
+ # available on the class version of +validates_with+, should instead be
+ # placed on the +validates+ method as these are applied and tested
# in the callback
#
# If you pass any additional configuration options, they will be passed
- # to the class and available as <tt>options</tt>, please refer to the
+ # to the class and available as +options+, please refer to the
# class version of this method for more information
#
def validates_with(*args, &block)
diff --git a/guides/assets/images/getting_started/confirm_dialog.png b/guides/assets/images/getting_started/confirm_dialog.png
new file mode 100644
index 0000000000..a26c09ef2d
--- /dev/null
+++ b/guides/assets/images/getting_started/confirm_dialog.png
Binary files differ
diff --git a/guides/assets/images/getting_started/undefined_method_post_path.png b/guides/assets/images/getting_started/undefined_method_post_path.png
new file mode 100644
index 0000000000..f568bf315c
--- /dev/null
+++ b/guides/assets/images/getting_started/undefined_method_post_path.png
Binary files differ
diff --git a/guides/code/getting_started/app/controllers/posts_controller.rb b/guides/code/getting_started/app/controllers/posts_controller.rb
index fc71e9b4e8..85d2c1de47 100644
--- a/guides/code/getting_started/app/controllers/posts_controller.rb
+++ b/guides/code/getting_started/app/controllers/posts_controller.rb
@@ -35,4 +35,11 @@ class PostsController < ApplicationController
render 'edit'
end
end
+
+ def destroy
+ @post = Post.find(params[:id])
+ @post.destroy
+
+ redirect_to :action => :index
+ end
end
diff --git a/guides/code/getting_started/app/views/posts/_form.html.erb b/guides/code/getting_started/app/views/posts/_form.html.erb
index 46ec257b91..b35ea2f237 100644
--- a/guides/code/getting_started/app/views/posts/_form.html.erb
+++ b/guides/code/getting_started/app/views/posts/_form.html.erb
@@ -1,4 +1,4 @@
-<%= form_for :post, :url => { :action => :update, :id => @post.id }, :method => :put do |f| %>
+<%= 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>
diff --git a/guides/code/getting_started/app/views/posts/index.html.erb b/guides/code/getting_started/app/views/posts/index.html.erb
index 3ba7091c15..7b72720d50 100644
--- a/guides/code/getting_started/app/views/posts/index.html.erb
+++ b/guides/code/getting_started/app/views/posts/index.html.erb
@@ -8,6 +8,7 @@
<th>Text</th>
<th></th>
<th></th>
+ <th></th>
</tr>
<% @posts.each do |post| %>
@@ -16,6 +17,7 @@
<td><%= post.text %></td>
<td><%= link_to 'Show', :action => :show, :id => post.id %>
<td><%= link_to 'Edit', :action => :edit, :id => post.id %>
+ <td><%= link_to 'Destroy', { :action => :destroy, :id => post.id }, :method => :delete, :confirm => 'Are you sure?' %>
</tr>
<% end %>
</table>
diff --git a/guides/code/getting_started/config/routes.rb b/guides/code/getting_started/config/routes.rb
index b0973c62d5..6095a05a58 100644
--- a/guides/code/getting_started/config/routes.rb
+++ b/guides/code/getting_started/config/routes.rb
@@ -6,9 +6,10 @@ Blog::Application.routes.draw do
get "posts" => "posts#index"
get "posts/new"
post "posts/create"
- get "posts/:id" => "posts#show"
+ get "posts/:id" => "posts#show", :as => :post
get "posts/:id/edit" => "posts#edit"
- put "posts/:id/update" => "posts#update"
+ put "posts/:id" => "posts#update"
+ delete "posts/:id" => "posts#destroy"
# The priority is based upon order of creation:
# first created -> highest priority.
diff --git a/guides/source/active_record_validations_callbacks.textile b/guides/source/active_record_validations_callbacks.textile
index 88c4481e5e..f49d91fd3c 100644
--- a/guides/source/active_record_validations_callbacks.textile
+++ b/guides/source/active_record_validations_callbacks.textile
@@ -1064,6 +1064,7 @@ Additionally, the +after_find+ callback is triggered by the following finder met
* +find_all_by_<em>attribute</em>+
* +find_by_<em>attribute</em>+
* +find_by_<em>attribute</em>!+
+* +find_by_sql+
* +last+
The +after_initialize+ callback is triggered every time a new object of the class is initialized.
@@ -1076,7 +1077,6 @@ Just as with validations, it is also possible to skip callbacks. These methods s
* +decrement_counter+
* +delete+
* +delete_all+
-* +find_by_sql+
* +increment+
* +increment_counter+
* +toggle+
diff --git a/guides/source/active_support_core_extensions.textile b/guides/source/active_support_core_extensions.textile
index 5d0a3f82e8..e4a6e145b9 100644
--- a/guides/source/active_support_core_extensions.textile
+++ b/guides/source/active_support_core_extensions.textile
@@ -1131,7 +1131,7 @@ h4. Output Safety
h5. Motivation
-Inserting data into HTML templates needs extra care. For example you can't just interpolate +@review.title+ verbatim into an HTML page. On one hand if the review title is "Flanagan & Matz rules!" the output won't be well-formed because an ampersand has to be escaped as "&amp;amp;". On the other hand, depending on the application that may be a big security hole because users can inject malicious HTML setting a hand-crafted review title. Check out the "section about cross-site scripting in the Security guide":security.html#cross-site-scripting-xss for further information about the risks.
+Inserting data into HTML templates needs extra care. For example, you can't just interpolate +@review.title+ verbatim into an HTML page. For one thing, if the review title is "Flanagan & Matz rules!" the output won't be well-formed because an ampersand has to be escaped as "&amp;amp;". What's more, depending on the application, that may be a big security hole because users can inject malicious HTML setting a hand-crafted review title. Check out the "section about cross-site scripting in the Security guide":security.html#cross-site-scripting-xss for further information about the risks.
h5. Safe Strings
diff --git a/guides/source/engines.textile b/guides/source/engines.textile
index 36210aedb0..71bcf6b713 100644
--- a/guides/source/engines.textile
+++ b/guides/source/engines.textile
@@ -695,7 +695,7 @@ If a template is rendered from within an engine and it's attempting to use one o
h4. Assets
-Assets within an engine work in an identical way to a full application. Because the engine class inherits from +Rails::Engine+, the application will know to look up in the engine's +app/assets+ directory for potential assets.
+Assets within an engine work in an identical way to a full application. Because the engine class inherits from +Rails::Engine+, the application will know to look up in the engine's +app/assets+ and +lib/assets+ directories for potential assets.
Much like all the other components of an engine, the assets should also be namespaced. This means if you have an asset called +style.css+, it should be placed at +app/assets/stylesheets/[engine name]/style.css+, rather than +app/assets/stylesheets/style.css+. If this asset wasn't namespaced, then there is a possibility that the host application could have an asset named identically, in which case the application's asset would take precedence and the engine's one would be all but ignored.
diff --git a/guides/source/generators.textile b/guides/source/generators.textile
index e9d713d91d..2e9ab0526d 100644
--- a/guides/source/generators.textile
+++ b/guides/source/generators.textile
@@ -468,7 +468,7 @@ Replaces text inside a file.
<ruby>
gsub_file 'name_of_file.rb', 'method.to_be_replaced', 'method.the_replacing_code'
-</ruby
+</ruby>
Regular Expressions can be used to make this method more precise. You can also use append_file and prepend_file in the same way to place code at the beginning and end of a file respectively.
diff --git a/guides/source/getting_started.textile b/guides/source/getting_started.textile
index 88d5ce6d9b..4c44b1ffec 100644
--- a/guides/source/getting_started.textile
+++ b/guides/source/getting_started.textile
@@ -465,7 +465,7 @@ invoking the command: <tt>rake db:migrate RAILS_ENV=production</tt>.
h4. Saving data in the controller
-Back into +posts_controller+, we need to change the +create+ action
+Back in +posts_controller+, we need to change the +create+ action
to use the new +Post+ model to save data in the database. Open that file
and change the +create+ action to look like the following:
@@ -835,7 +835,7 @@ Moving on, we need to add the +update+ action. The file
+config/routes.rb+ will need just one more line:
<ruby>
-put "posts/:id/update"
+put "posts/:id" => "posts#update"
</ruby>
And the +update+ action in +posts_controller+ itself should not look too complicated by now:
@@ -930,6 +930,175 @@ Our +edit+ action looks very similar to the +new+ action, in fact they
both share the same code for displaying the form. Lets clean them up by
using a +_form+ partial.
+Create a new file +app/views/posts/_form.html.erb+ with the following
+content:
+
+<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 %>
+ <p>
+ <%= f.label :title %><br>
+ <%= f.text_field :title %>
+ </p>
+
+ <p>
+ <%= f.label :text %><br>
+ <%= f.text_area :text %>
+ </p>
+
+ <p>
+ <%= f.submit %>
+ </p>
+<% end %>
+</erb>
+
+Everything except for the +form_for+ declaration remained the same. I'll
+explain later how +form_for+ can figure out the right +action+ and
++method+ attributes when building the form, for now let's update the
++new+ and +edit+ views:
+
+<erb>
+# app/views/posts/new.html.erb
+
+<h1>New post</h1>
+
+<%= render 'form' %>
+
+<%= link_to 'Back', :action => :index %>
+
+
+# app/views/posts/edit.html.erb
+
+<h1>Edit post</h1>
+
+<%= render 'form' %>
+
+<%= link_to 'Back', :action => :index %>
+</erb>
+
+Point your browser to
+"http://localhost:3000/posts/new":http://localhost:3000/posts/new and
+try creating a new post. Everything still works. Now try editing the
+post and you'll receive the following error:
+
+!images/getting_started/undefined_method_post_path.png(Undefined method
+post_path)!
+
+To understand this error, you need to understand how +form_for+ works.
+When you pass an object to +form_for+ and you don't specify a +:url+
+option, Rails will try to guess the +action+ and +method+ options by
+checking if the passed object is a new record or not. Rails follows the
+REST convention, so to create a new +Post+ object it will look for a
+route named +posts_path+, and to update a +Post+ object it will look for
+a route named +post_path+ and pass the current object. Similarly, rails
+knows that it should create new objects via POST and update them via
+PUT.
+
+If you run +rake routes+ from the console you'll see that we already
+have a +posts_path+ route, which was created automatically by Rails.
+However, we don't have a +post_path+ yet, which is the reason why we
+received an error before.
+
+<shell>
+# rake routes
+
+ posts GET /posts(.:format) posts#index
+ posts_new GET /posts/new(.:format) posts#new
+posts_create POST /posts/create(.:format) posts#create
+ GET /posts/:id(.:format) posts#show
+ GET /posts/:id/edit(.:format) posts#edit
+ PUT /posts/:id(.:format) posts#update
+ root / welcome#index
+</shell>
+
+To fix this, open +config/routes.rb+ and modify the +get "posts/:id"+
+line like this:
+
+<ruby>
+get "posts/:id" => "posts#show", :as => :post
+</ruby>
+
+Now you'll be able to update posts again.
+
+h4. Deleting Posts
+
+We're now ready to cover the "D" part of CRUD, deleting posts from the
+database. Following the REST convention, we're going to add a route for
+deleting posts:
+
+<ruby>
+# config/routes.rb
+
+delete "posts/:id" => "posts#destroy"
+</ruby>
+
+We use the +delete+ method for destroying resources, which is mapped to
+the +destroy+ action, which is provided below:
+
+<ruby>
+# app/controllers/posts_controller.rb
+
+def destroy
+ @post = Post.find(params[:id])
+ @post.destroy
+
+ redirect_to :action => :index
+end
+</ruby>
+
+You can call +destroy+ on Active Record objects when you want to delete
+them from the dabase. Note that we don't need to add a view for this
+action since we're redirecting to the +index+ action.
+
+Finally, add a 'destroy' link to your +index+ action to wrap everything
+together.
+
+<erb>
+<table>
+ <tr>
+ <th>Title</th>
+ <th>Text</th>
+ <th></th>
+ <th></th>
+ <th></th>
+ </tr>
+
+<% @posts.each do |post| %>
+ <tr>
+ <td><%= post.title %></td>
+ <td><%= post.text %></td>
+ <td><%= link_to 'Show', :action => :show, :id => post.id %></td>
+ <td><%= link_to 'Edit', :action => :edit, :id => post.id %></td>
+ <td><%= link_to 'Destroy', { :action => :destroy, :id => post.id }, :method => :delete, :confirm => 'Are you sure?' %></td>
+ </tr>
+<% end %>
+</table>
+</erb>
+
+Here we're using +link_to+ in a different way. We wrap the
++:action+ and +:id+ attributes in a hash so that we can pass other
+arguments to +link_to+. The +:method+ and +:confirm+
+options are used as html5 attributes so that when the click is linked,
+Rails will first show a confirm dialog to the user, and then submit the
+link with method +delete+. This is done via javascript automatically.
+
+!images/getting_started/confirm_dialog.png(Confirm Dialog)!
+
+Congratulations, you can now create, show, list, update and destroy
+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
To see your validations in action, you can use the console. The console is a
diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb
index d8ca6cbd21..493eacdc5a 100644
--- a/railties/lib/rails/configuration.rb
+++ b/railties/lib/rails/configuration.rb
@@ -16,7 +16,7 @@ module Rails
#
# config.middleware.use Magical::Unicorns
#
- # This will put the +Magical::Unicorns+ middleware on the end of the stack.
+ # This will put the <tt>Magical::Unicorns</tt> middleware on the end of the stack.
# You can use +insert_before+ if you wish to add a middleware before another:
#
# config.middleware.insert_before ActionDispatch::Head, Magical::Unicorns
diff --git a/railties/lib/rails/generators/test_case.rb b/railties/lib/rails/generators/test_case.rb
index 2cb34fab7a..508e221c60 100644
--- a/railties/lib/rails/generators/test_case.rb
+++ b/railties/lib/rails/generators/test_case.rb
@@ -79,8 +79,8 @@ module Rails
#
# Finally, when a block is given, it yields the file content:
#
- # assert_file "app/controller/products_controller.rb" do |controller|
- # assert_instance_method :index, content do |index|
+ # assert_file "app/controllers/products_controller.rb" do |controller|
+ # assert_instance_method :index, controller do |index|
# assert_match(/Product\.all/, index)
# end
# end
@@ -159,8 +159,8 @@ module Rails
# Asserts the given method exists in the given content. When a block is given,
# it yields the content of the method.
#
- # assert_file "app/controller/products_controller.rb" do |controller|
- # assert_instance_method :index, content do |index|
+ # assert_file "app/controllers/products_controller.rb" do |controller|
+ # assert_instance_method :index, controller do |index|
# assert_match(/Product\.all/, index)
# end
# end
diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb
index fced6f8896..b787d91821 100644
--- a/railties/lib/rails/paths.rb
+++ b/railties/lib/rails/paths.rb
@@ -10,7 +10,7 @@ module Rails
# root.add "app/controllers", :eager_load => true
#
# The command above creates a new root object and add "app/controllers" as a path.
- # This means we can get a +Rails::Paths::Path+ object back like below:
+ # This means we can get a <tt>Rails::Paths::Path</tt> object back like below:
#
# path = root["app/controllers"]
# path.eager_load? # => true