diff options
author | Vijay Dev <vijaydev.cse@gmail.com> | 2012-04-28 00:56:17 +0530 |
---|---|---|
committer | Vijay Dev <vijaydev.cse@gmail.com> | 2012-04-28 00:56:17 +0530 |
commit | 43af34c0f6c81d4d93be1bc1e743c202e8244485 (patch) | |
tree | 1792c580a3138baf710b632110861f5d68f4de63 | |
parent | 50b1399b3128fcba73bf3478e22d187090921872 (diff) | |
parent | fc3d15dcb0c4265d1aaeedfc51d8a8c8e382347a (diff) | |
download | rails-43af34c0f6c81d4d93be1bc1e743c202e8244485.tar.gz rails-43af34c0f6c81d4d93be1bc1e743c202e8244485.tar.bz2 rails-43af34c0f6c81d4d93be1bc1e743c202e8244485.zip |
Merge branch 'master' of github.com:lifo/docrails
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 Binary files differnew file mode 100644 index 0000000000..a26c09ef2d --- /dev/null +++ b/guides/assets/images/getting_started/confirm_dialog.png diff --git a/guides/assets/images/getting_started/undefined_method_post_path.png b/guides/assets/images/getting_started/undefined_method_post_path.png Binary files differnew file mode 100644 index 0000000000..f568bf315c --- /dev/null +++ b/guides/assets/images/getting_started/undefined_method_post_path.png 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;". 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;". 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 |