aboutsummaryrefslogtreecommitdiffstats
path: root/guides
diff options
context:
space:
mode:
Diffstat (limited to 'guides')
-rw-r--r--guides/assets/images/favicon.icobin0 -> 1150 bytes
-rw-r--r--guides/assets/images/getting_started/confirm_dialog.pngbin0 -> 36070 bytes
-rw-r--r--guides/assets/images/getting_started/form_with_errors.pngbin0 -> 20820 bytes
-rw-r--r--guides/assets/images/getting_started/index_action_with_edit_link.pngbin0 -> 15547 bytes
-rw-r--r--guides/assets/images/getting_started/show_action_for_posts.pngbin0 -> 6885 bytes
-rw-r--r--guides/assets/images/getting_started/undefined_method_post_path.pngbin0 -> 15254 bytes
-rw-r--r--guides/assets/images/posts_index.pngbin60846 -> 0 bytes
-rw-r--r--guides/assets/stylesheets/main.css6
-rw-r--r--guides/code/getting_started/Gemfile8
-rw-r--r--guides/code/getting_started/README.rdoc4
-rw-r--r--guides/code/getting_started/app/assets/javascripts/comments.js.coffee3
-rw-r--r--guides/code/getting_started/app/assets/javascripts/home.js.coffee3
-rw-r--r--guides/code/getting_started/app/assets/javascripts/posts.js.coffee3
-rw-r--r--guides/code/getting_started/app/assets/stylesheets/comments.css.scss3
-rw-r--r--guides/code/getting_started/app/assets/stylesheets/home.css.scss3
-rw-r--r--guides/code/getting_started/app/assets/stylesheets/posts.css.scss3
-rw-r--r--guides/code/getting_started/app/assets/stylesheets/scaffolds.css.scss56
-rw-r--r--guides/code/getting_started/app/controllers/home_controller.rb2
-rw-r--r--guides/code/getting_started/app/controllers/posts_controller.rb67
-rw-r--r--guides/code/getting_started/app/helpers/home_helper.rb2
-rw-r--r--guides/code/getting_started/app/helpers/posts_helper.rb3
-rw-r--r--guides/code/getting_started/app/helpers/welcome_helper.rb2
-rw-r--r--guides/code/getting_started/app/models/post.rb7
-rw-r--r--guides/code/getting_started/app/models/tag.rb3
-rw-r--r--guides/code/getting_started/app/views/home/index.html.erb2
-rw-r--r--guides/code/getting_started/app/views/posts/_form.html.erb51
-rw-r--r--guides/code/getting_started/app/views/posts/edit.html.erb3
-rw-r--r--guides/code/getting_started/app/views/posts/index.html.erb18
-rw-r--r--guides/code/getting_started/app/views/posts/new.html.erb2
-rw-r--r--guides/code/getting_started/app/views/posts/show.html.erb33
-rw-r--r--guides/code/getting_started/app/views/tags/_form.html.erb12
-rw-r--r--guides/code/getting_started/app/views/welcome/index.html.erb2
-rw-r--r--guides/code/getting_started/config/environments/production.rb2
-rw-r--r--guides/code/getting_started/config/routes.rb18
-rw-r--r--guides/code/getting_started/db/migrate/20110901013701_create_tags.rb11
-rw-r--r--guides/code/getting_started/db/migrate/20120420083127_create_posts.rb (renamed from guides/code/getting_started/db/migrate/20110901012504_create_posts.rb)3
-rw-r--r--guides/code/getting_started/db/schema.rb17
-rw-r--r--guides/code/getting_started/test/fixtures/posts.yml6
-rw-r--r--guides/code/getting_started/test/functional/home_controller_test.rb2
-rw-r--r--guides/code/getting_started/vendor/assets/stylesheets/.gitkeep0
-rw-r--r--guides/source/3_2_release_notes.textile2
-rw-r--r--guides/source/action_controller_overview.textile9
-rw-r--r--guides/source/action_view_overview.textile24
-rw-r--r--guides/source/active_record_querying.textile101
-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/api_documentation_guidelines.textile45
-rw-r--r--guides/source/asset_pipeline.textile18
-rw-r--r--guides/source/association_basics.textile4
-rw-r--r--guides/source/caching_with_rails.textile20
-rw-r--r--guides/source/command_line.textile6
-rw-r--r--guides/source/configuring.textile23
-rw-r--r--guides/source/contributing_to_ruby_on_rails.textile113
-rw-r--r--guides/source/debugging_rails_applications.textile39
-rw-r--r--guides/source/engines.textile83
-rw-r--r--guides/source/form_helpers.textile2
-rw-r--r--guides/source/generators.textile21
-rw-r--r--guides/source/getting_started.textile697
-rw-r--r--guides/source/i18n.textile26
-rw-r--r--guides/source/layout.html.erb2
-rw-r--r--guides/source/layouts_and_rendering.textile34
-rw-r--r--guides/source/migrations.textile32
-rw-r--r--guides/source/plugins.textile10
-rw-r--r--guides/source/rails_on_rack.textile123
-rw-r--r--guides/source/routing.textile103
-rw-r--r--guides/source/ruby_on_rails_guides_guidelines.textile19
-rw-r--r--guides/source/security.textile2
-rw-r--r--guides/source/testing.textile40
-rw-r--r--guides/w3c_validator.rb2
69 files changed, 1301 insertions, 663 deletions
diff --git a/guides/assets/images/favicon.ico b/guides/assets/images/favicon.ico
new file mode 100644
index 0000000000..e0e80cf8f1
--- /dev/null
+++ b/guides/assets/images/favicon.ico
Binary files differ
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/form_with_errors.png b/guides/assets/images/getting_started/form_with_errors.png
new file mode 100644
index 0000000000..badefe6ea6
--- /dev/null
+++ b/guides/assets/images/getting_started/form_with_errors.png
Binary files differ
diff --git a/guides/assets/images/getting_started/index_action_with_edit_link.png b/guides/assets/images/getting_started/index_action_with_edit_link.png
new file mode 100644
index 0000000000..6e58a13756
--- /dev/null
+++ b/guides/assets/images/getting_started/index_action_with_edit_link.png
Binary files differ
diff --git a/guides/assets/images/getting_started/show_action_for_posts.png b/guides/assets/images/getting_started/show_action_for_posts.png
new file mode 100644
index 0000000000..5c8c4d8e5e
--- /dev/null
+++ b/guides/assets/images/getting_started/show_action_for_posts.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/assets/images/posts_index.png b/guides/assets/images/posts_index.png
deleted file mode 100644
index f6cd2f9b80..0000000000
--- a/guides/assets/images/posts_index.png
+++ /dev/null
Binary files differ
diff --git a/guides/assets/stylesheets/main.css b/guides/assets/stylesheets/main.css
index 90723cc8e1..42b85fefa3 100644
--- a/guides/assets/stylesheets/main.css
+++ b/guides/assets/stylesheets/main.css
@@ -80,7 +80,7 @@ body {
font-family: Helvetica, Arial, sans-serif;
font-size: 87.5%;
line-height: 1.5em;
- background: #222;
+ background: #fff;
min-width: 69em;
color: #999;
}
@@ -94,6 +94,7 @@ body {
#topNav {
padding: 1em 0;
color: #565656;
+ background: #222;
}
#header {
@@ -111,7 +112,6 @@ body {
}
#container {
- background: #FFF;
color: #333;
padding: 0.5em 0 1.5em 0;
}
@@ -137,7 +137,7 @@ body {
#footer {
padding: 2em 0;
- background: url(../images/footer_tile.gif) repeat-x;
+ background: #222 url(../images/footer_tile.gif) repeat-x;
}
#footer .wrapper {
padding-left: 2em;
diff --git a/guides/code/getting_started/Gemfile b/guides/code/getting_started/Gemfile
index 768985070c..670a8523b0 100644
--- a/guides/code/getting_started/Gemfile
+++ b/guides/code/getting_started/Gemfile
@@ -1,6 +1,6 @@
source 'https://rubygems.org'
-gem 'rails', '3.2.0'
+gem 'rails', '3.2.3'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
@@ -15,7 +15,7 @@ group :assets do
gem 'coffee-rails', '~> 3.2.1'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
- # gem 'therubyracer'
+ # gem 'therubyracer', :platform => :ruby
gem 'uglifier', '>= 1.0.3'
end
@@ -28,11 +28,11 @@ gem 'jquery-rails'
# To use Jbuilder templates for JSON
# gem 'jbuilder'
-# Use unicorn as the web server
+# Use unicorn as the app server
# gem 'unicorn'
# Deploy with Capistrano
# gem 'capistrano'
# To use debugger
-# gem 'ruby-debug19', :require => 'ruby-debug'
+# gem 'debugger'
diff --git a/guides/code/getting_started/README.rdoc b/guides/code/getting_started/README.rdoc
index d2014bd35f..b5d7b6436b 100644
--- a/guides/code/getting_started/README.rdoc
+++ b/guides/code/getting_started/README.rdoc
@@ -86,8 +86,8 @@ programming in general.
Debugger support is available through the debugger command when you start your
Mongrel or WEBrick server with --debugger. This means that you can break out of
execution at any point in the code, investigate and change the model, and then,
-resume execution! You need to install ruby-debug19 to run the server in debugging
-mode. With gems, use <tt>sudo gem install ruby-debug19</tt>. Example:
+resume execution! You need to install the 'debugger' gem to run the server in debugging
+mode. Add gem 'debugger' to your Gemfile and run <tt>bundle</tt> to install it. Example:
class WeblogController < ActionController::Base
def index
diff --git a/guides/code/getting_started/app/assets/javascripts/comments.js.coffee b/guides/code/getting_started/app/assets/javascripts/comments.js.coffee
deleted file mode 100644
index 761567942f..0000000000
--- a/guides/code/getting_started/app/assets/javascripts/comments.js.coffee
+++ /dev/null
@@ -1,3 +0,0 @@
-# Place all the behaviors and hooks related to the matching controller here.
-# All this logic will automatically be available in application.js.
-# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
diff --git a/guides/code/getting_started/app/assets/javascripts/home.js.coffee b/guides/code/getting_started/app/assets/javascripts/home.js.coffee
deleted file mode 100644
index 761567942f..0000000000
--- a/guides/code/getting_started/app/assets/javascripts/home.js.coffee
+++ /dev/null
@@ -1,3 +0,0 @@
-# Place all the behaviors and hooks related to the matching controller here.
-# All this logic will automatically be available in application.js.
-# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
diff --git a/guides/code/getting_started/app/assets/javascripts/posts.js.coffee b/guides/code/getting_started/app/assets/javascripts/posts.js.coffee
deleted file mode 100644
index 761567942f..0000000000
--- a/guides/code/getting_started/app/assets/javascripts/posts.js.coffee
+++ /dev/null
@@ -1,3 +0,0 @@
-# Place all the behaviors and hooks related to the matching controller here.
-# All this logic will automatically be available in application.js.
-# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
diff --git a/guides/code/getting_started/app/assets/stylesheets/comments.css.scss b/guides/code/getting_started/app/assets/stylesheets/comments.css.scss
deleted file mode 100644
index e730912783..0000000000
--- a/guides/code/getting_started/app/assets/stylesheets/comments.css.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-// Place all the styles related to the Comments controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/guides/code/getting_started/app/assets/stylesheets/home.css.scss b/guides/code/getting_started/app/assets/stylesheets/home.css.scss
deleted file mode 100644
index f0ddc6846a..0000000000
--- a/guides/code/getting_started/app/assets/stylesheets/home.css.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-// Place all the styles related to the home controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/guides/code/getting_started/app/assets/stylesheets/posts.css.scss b/guides/code/getting_started/app/assets/stylesheets/posts.css.scss
deleted file mode 100644
index ed4dfd10f2..0000000000
--- a/guides/code/getting_started/app/assets/stylesheets/posts.css.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-// Place all the styles related to the Posts controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/guides/code/getting_started/app/assets/stylesheets/scaffolds.css.scss b/guides/code/getting_started/app/assets/stylesheets/scaffolds.css.scss
deleted file mode 100644
index 05188f08ed..0000000000
--- a/guides/code/getting_started/app/assets/stylesheets/scaffolds.css.scss
+++ /dev/null
@@ -1,56 +0,0 @@
-body {
- background-color: #fff;
- color: #333;
- font-family: verdana, arial, helvetica, sans-serif;
- font-size: 13px;
- line-height: 18px; }
-
-p, ol, ul, td {
- font-family: verdana, arial, helvetica, sans-serif;
- font-size: 13px;
- line-height: 18px; }
-
-pre {
- background-color: #eee;
- padding: 10px;
- font-size: 11px; }
-
-a {
- color: #000;
- &:visited {
- color: #666; }
- &:hover {
- color: #fff;
- background-color: #000; } }
-
-div {
- &.field, &.actions {
- margin-bottom: 10px; } }
-
-#notice {
- color: green; }
-
-.field_with_errors {
- padding: 2px;
- background-color: red;
- display: table; }
-
-#error_explanation {
- width: 450px;
- border: 2px solid red;
- padding: 7px;
- padding-bottom: 0;
- margin-bottom: 20px;
- background-color: #f0f0f0;
- h2 {
- text-align: left;
- font-weight: bold;
- padding: 5px 5px 5px 15px;
- font-size: 12px;
- margin: -7px;
- margin-bottom: 0px;
- background-color: #c00;
- color: #fff; }
- ul li {
- font-size: 12px;
- list-style: square; } }
diff --git a/guides/code/getting_started/app/controllers/home_controller.rb b/guides/code/getting_started/app/controllers/home_controller.rb
index 6cc31c1ca3..309b70441e 100644
--- a/guides/code/getting_started/app/controllers/home_controller.rb
+++ b/guides/code/getting_started/app/controllers/home_controller.rb
@@ -1,4 +1,4 @@
-class HomeController < ApplicationController
+class WelcomeController < ApplicationController
def index
end
diff --git a/guides/code/getting_started/app/controllers/posts_controller.rb b/guides/code/getting_started/app/controllers/posts_controller.rb
index 1581d4eb16..85d2c1de47 100644
--- a/guides/code/getting_started/app/controllers/posts_controller.rb
+++ b/guides/code/getting_started/app/controllers/posts_controller.rb
@@ -1,84 +1,45 @@
class PostsController < ApplicationController
- http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index
- # GET /posts
- # GET /posts.json
+
def index
@posts = Post.all
-
- respond_to do |format|
- format.html # index.html.erb
- format.json { render json: @posts }
- end
end
- # GET /posts/1
- # GET /posts/1.json
def show
@post = Post.find(params[:id])
-
- respond_to do |format|
- format.html # show.html.erb
- format.json { render json: @post }
- end
end
- # GET /posts/new
- # GET /posts/new.json
def new
@post = Post.new
-
- respond_to do |format|
- format.html # new.html.erb
- format.json { render json: @post }
- end
- end
-
- # GET /posts/1/edit
- def edit
- @post = Post.find(params[:id])
end
- # POST /posts
- # POST /posts.json
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
+ if @post.save
+ redirect_to :action => :show, :id => @post.id
+ else
+ render 'new'
end
end
- # PUT /posts/1
- # PUT /posts/1.json
+ def edit
+ @post = Post.find(params[:id])
+ end
+
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
+ if @post.update_attributes(params[:post])
+ redirect_to :action => :show, :id => @post.id
+ else
+ render 'edit'
end
end
- # DELETE /posts/1
- # DELETE /posts/1.json
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
+ redirect_to :action => :index
end
end
diff --git a/guides/code/getting_started/app/helpers/home_helper.rb b/guides/code/getting_started/app/helpers/home_helper.rb
deleted file mode 100644
index 23de56ac60..0000000000
--- a/guides/code/getting_started/app/helpers/home_helper.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-module HomeHelper
-end
diff --git a/guides/code/getting_started/app/helpers/posts_helper.rb b/guides/code/getting_started/app/helpers/posts_helper.rb
index b6e8e67894..a7b8cec898 100644
--- a/guides/code/getting_started/app/helpers/posts_helper.rb
+++ b/guides/code/getting_started/app/helpers/posts_helper.rb
@@ -1,5 +1,2 @@
module PostsHelper
- def join_tags(post)
- post.tags.map { |t| t.name }.join(", ")
- end
end
diff --git a/guides/code/getting_started/app/helpers/welcome_helper.rb b/guides/code/getting_started/app/helpers/welcome_helper.rb
new file mode 100644
index 0000000000..eeead45fc9
--- /dev/null
+++ b/guides/code/getting_started/app/helpers/welcome_helper.rb
@@ -0,0 +1,2 @@
+module WelcomeHelper
+end
diff --git a/guides/code/getting_started/app/models/post.rb b/guides/code/getting_started/app/models/post.rb
index 61c2b5ae44..21387340b0 100644
--- a/guides/code/getting_started/app/models/post.rb
+++ b/guides/code/getting_started/app/models/post.rb
@@ -1,11 +1,6 @@
class Post < ActiveRecord::Base
- validates :name, :presence => true
validates :title, :presence => true,
:length => { :minimum => 5 }
-
+
has_many :comments, :dependent => :destroy
- has_many :tags
-
- accepts_nested_attributes_for :tags, :allow_destroy => :true,
- :reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } }
end
diff --git a/guides/code/getting_started/app/models/tag.rb b/guides/code/getting_started/app/models/tag.rb
deleted file mode 100644
index 30992e8ba9..0000000000
--- a/guides/code/getting_started/app/models/tag.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-class Tag < ActiveRecord::Base
- belongs_to :post
-end
diff --git a/guides/code/getting_started/app/views/home/index.html.erb b/guides/code/getting_started/app/views/home/index.html.erb
deleted file mode 100644
index bb4f3dcd1f..0000000000
--- a/guides/code/getting_started/app/views/home/index.html.erb
+++ /dev/null
@@ -1,2 +0,0 @@
-<h1>Hello, Rails!</h1>
-<%= link_to "My Blog", posts_path %>
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 e27da7f413..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,32 +1,25 @@
-<% @post.tags.build %>
-<%= form_for(@post) do |post_form| %>
+<%= 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>
+ <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">
- <%= post_form.label :name %><br />
- <%= post_form.text_field :name %>
- </div>
- <div class="field">
- <%= post_form.label :title %><br />
- <%= post_form.text_field :title %>
- </div>
- <div class="field">
- <%= post_form.label :content %><br />
- <%= post_form.text_area :content %>
- </div>
- <h2>Tags</h2>
- <%= render :partial => 'tags/form',
- :locals => {:form => post_form} %>
- <div class="actions">
- <%= post_form.submit %>
- </div>
+ <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 %>
diff --git a/guides/code/getting_started/app/views/posts/edit.html.erb b/guides/code/getting_started/app/views/posts/edit.html.erb
index 720580236b..911a48569d 100644
--- a/guides/code/getting_started/app/views/posts/edit.html.erb
+++ b/guides/code/getting_started/app/views/posts/edit.html.erb
@@ -2,5 +2,4 @@
<%= render 'form' %>
-<%= link_to 'Show', @post %> |
-<%= link_to 'Back', posts_path %>
+<%= link_to 'Back', :action => :index %>
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 45dee1b25f..7b72720d50 100644
--- a/guides/code/getting_started/app/views/posts/index.html.erb
+++ b/guides/code/getting_started/app/views/posts/index.html.erb
@@ -1,10 +1,11 @@
<h1>Listing posts</h1>
+<%= link_to 'New post', :action => :new %>
+
<table>
<tr>
- <th>Name</th>
<th>Title</th>
- <th>Content</th>
+ <th>Text</th>
<th></th>
<th></th>
<th></th>
@@ -12,16 +13,11 @@
<% @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>
+ <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>
-
-<br />
-
-<%= link_to 'New Post', new_post_path %>
diff --git a/guides/code/getting_started/app/views/posts/new.html.erb b/guides/code/getting_started/app/views/posts/new.html.erb
index 36ad7421f9..ce9523a721 100644
--- a/guides/code/getting_started/app/views/posts/new.html.erb
+++ b/guides/code/getting_started/app/views/posts/new.html.erb
@@ -2,4 +2,4 @@
<%= render 'form' %>
-<%= link_to 'Back', posts_path %>
+<%= link_to 'Back', :action => :index %>
diff --git a/guides/code/getting_started/app/views/posts/show.html.erb b/guides/code/getting_started/app/views/posts/show.html.erb
index da78a9527b..aea28cd5a2 100644
--- a/guides/code/getting_started/app/views/posts/show.html.erb
+++ b/guides/code/getting_started/app/views/posts/show.html.erb
@@ -1,31 +1,12 @@
-<p class="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 %>
-</p>
-
+
<p>
- <b>Tags:</b>
- <%= join_tags(@post) %>
+ <strong>Text:</strong>
+ <%= @post.text %>
</p>
-
-<h2>Comments</h2>
-<%= render @post.comments %>
-
-<h2>Add a comment:</h2>
-<%= render "comments/form" %>
-
-
-<%= link_to 'Edit Post', edit_post_path(@post) %> |
-<%= link_to 'Back to Posts', posts_path %> |
+
+<%= link_to 'Back', :action => :index %>
+| <%= link_to 'Edit', :action => :edit, :id => @post.id %>
diff --git a/guides/code/getting_started/app/views/tags/_form.html.erb b/guides/code/getting_started/app/views/tags/_form.html.erb
deleted file mode 100644
index 7e424b0e20..0000000000
--- a/guides/code/getting_started/app/views/tags/_form.html.erb
+++ /dev/null
@@ -1,12 +0,0 @@
-<%= form.fields_for :tags do |tag_form| %>
- <div class="field">
- <%= tag_form.label :name, 'Tag:' %>
- <%= tag_form.text_field :name %>
- </div>
- <% unless tag_form.object.nil? || tag_form.object.new_record? %>
- <div class="field">
- <%= tag_form.label :_destroy, 'Remove:' %>
- <%= tag_form.check_box :_destroy %>
- </div>
- <% end %>
-<% end %>
diff --git a/guides/code/getting_started/app/views/welcome/index.html.erb b/guides/code/getting_started/app/views/welcome/index.html.erb
new file mode 100644
index 0000000000..e04680ea7e
--- /dev/null
+++ b/guides/code/getting_started/app/views/welcome/index.html.erb
@@ -0,0 +1,2 @@
+<h1>Hello, Rails!</h1>
+<%= link_to "My Blog", :controller => "posts" %>
diff --git a/guides/code/getting_started/config/environments/production.rb b/guides/code/getting_started/config/environments/production.rb
index cfb8c960d6..ecc35b030b 100644
--- a/guides/code/getting_started/config/environments/production.rb
+++ b/guides/code/getting_started/config/environments/production.rb
@@ -20,7 +20,7 @@ Blog::Application.configure do
# Generate digests for assets URLs.
config.assets.digest = true
- # Defaults to Rails.root.join("public/assets").
+ # Defaults to nil
# config.assets.manifest = YOUR_PATH
# Specifies the header that your server uses for sending files.
diff --git a/guides/code/getting_started/config/routes.rb b/guides/code/getting_started/config/routes.rb
index b048ac68f1..6095a05a58 100644
--- a/guides/code/getting_started/config/routes.rb
+++ b/guides/code/getting_started/config/routes.rb
@@ -1,9 +1,15 @@
Blog::Application.routes.draw do
- resources :posts do
- resources :comments
- end
+ # resources :posts do
+ # resources :comments
+ # end
- get "home/index"
+ 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"
# The priority is based upon order of creation:
# first created -> highest priority.
@@ -54,8 +60,8 @@ Blog::Application.routes.draw do
# You can have the root of your site routed with "root"
# just remember to delete public/index.html.
- root :to => "home#index"
-
+ root :to => "welcome#index"
+
# See how all your routes lay out with "rake routes"
# This is a legacy wild controller route that's not recommended for RESTful applications.
diff --git a/guides/code/getting_started/db/migrate/20110901013701_create_tags.rb b/guides/code/getting_started/db/migrate/20110901013701_create_tags.rb
deleted file mode 100644
index cf95b1c3d0..0000000000
--- a/guides/code/getting_started/db/migrate/20110901013701_create_tags.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-class CreateTags < ActiveRecord::Migration
- def change
- create_table :tags do |t|
- t.string :name
- t.references :post
-
- t.timestamps
- end
- add_index :tags, :post_id
- end
-end
diff --git a/guides/code/getting_started/db/migrate/20110901012504_create_posts.rb b/guides/code/getting_started/db/migrate/20120420083127_create_posts.rb
index d45a961523..602bef31ab 100644
--- a/guides/code/getting_started/db/migrate/20110901012504_create_posts.rb
+++ b/guides/code/getting_started/db/migrate/20120420083127_create_posts.rb
@@ -1,9 +1,8 @@
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
- t.string :name
t.string :title
- t.text :content
+ t.text :text
t.timestamps
end
diff --git a/guides/code/getting_started/db/schema.rb b/guides/code/getting_started/db/schema.rb
index 9db4fbe4b6..cfb56ca9b9 100644
--- a/guides/code/getting_started/db/schema.rb
+++ b/guides/code/getting_started/db/schema.rb
@@ -11,31 +11,30 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20110901013701) do
+ActiveRecord::Schema.define(:version => 20120420083127) do
create_table "comments", :force => true do |t|
t.string "commenter"
t.text "body"
t.integer "post_id"
- t.datetime "created_at"
- t.datetime "updated_at"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
end
add_index "comments", ["post_id"], :name => "index_comments_on_post_id"
create_table "posts", :force => true do |t|
- t.string "name"
t.string "title"
- t.text "content"
- t.datetime "created_at"
- t.datetime "updated_at"
+ t.text "text"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
end
create_table "tags", :force => true do |t|
t.string "name"
t.integer "post_id"
- t.datetime "created_at"
- t.datetime "updated_at"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
end
add_index "tags", ["post_id"], :name => "index_tags_on_post_id"
diff --git a/guides/code/getting_started/test/fixtures/posts.yml b/guides/code/getting_started/test/fixtures/posts.yml
index 8b0f75a33d..e1edfd385e 100644
--- a/guides/code/getting_started/test/fixtures/posts.yml
+++ b/guides/code/getting_started/test/fixtures/posts.yml
@@ -1,11 +1,9 @@
# Read about fixtures at http://api.rubyonrails.org/classes/Fixtures.html
one:
- name: MyString
title: MyString
- content: MyText
+ text: MyText
two:
- name: MyString
title: MyString
- content: MyText
+ text: MyText
diff --git a/guides/code/getting_started/test/functional/home_controller_test.rb b/guides/code/getting_started/test/functional/home_controller_test.rb
index 0d9bb47c3e..dff8e9d2c5 100644
--- a/guides/code/getting_started/test/functional/home_controller_test.rb
+++ b/guides/code/getting_started/test/functional/home_controller_test.rb
@@ -1,6 +1,6 @@
require 'test_helper'
-class HomeControllerTest < ActionController::TestCase
+class WelcomeControllerTest < ActionController::TestCase
test "should get index" do
get :index
assert_response :success
diff --git a/guides/code/getting_started/vendor/assets/stylesheets/.gitkeep b/guides/code/getting_started/vendor/assets/stylesheets/.gitkeep
deleted file mode 100644
index e69de29bb2..0000000000
--- a/guides/code/getting_started/vendor/assets/stylesheets/.gitkeep
+++ /dev/null
diff --git a/guides/source/3_2_release_notes.textile b/guides/source/3_2_release_notes.textile
index 0f8fea2bf6..3524ea6595 100644
--- a/guides/source/3_2_release_notes.textile
+++ b/guides/source/3_2_release_notes.textile
@@ -299,7 +299,7 @@ end
h5(#actionview_deprecations). Deprecations
-* Passing formats or handlers to render :template and friends like <tt>render :template => "foo.html.erb"</tt> is deprecated. Instead, you can provide :handlers and :formats directly as an options: <tt> render :template => "foo", :formats => [:html, :js], :handlers => :erb</tt>.
+* Passing formats or handlers to render :template and friends like <tt>render :template => "foo.html.erb"</tt> is deprecated. Instead, you can provide :handlers and :formats directly as options: <tt> render :template => "foo", :formats => [:html, :js], :handlers => :erb</tt>.
h4. Sprockets
diff --git a/guides/source/action_controller_overview.textile b/guides/source/action_controller_overview.textile
index 52d134ace5..cc3350819b 100644
--- a/guides/source/action_controller_overview.textile
+++ b/guides/source/action_controller_overview.textile
@@ -148,18 +148,19 @@ In this case, when a user opens the URL +/clients/active+, +params[:status]+ wil
h4. +default_url_options+
-You can set global default parameters that will be used when generating URLs with +default_url_options+. To do this, define a method with that name in your controller:
+You can set global default parameters for URL generation by defining a method called +default_url_options+ in your controller. Such a method must return a hash with the desired defaults, whose keys must be symbols:
<ruby>
class ApplicationController < ActionController::Base
- # The options parameter is the hash passed in to 'url_for'
- def default_url_options(options)
+ def default_url_options
{:locale => I18n.locale}
end
end
</ruby>
-These options will be used as a starting-point when generating URLs, so it's possible they'll be overridden by +url_for+. Because this method is defined in the controller, you can define it on +ApplicationController+ so it would be used for all URL generation, or you could define it on only one controller for all URLs generated there.
+These options will be used as a starting point when generating URLs, so it's possible they'll be overridden by the options passed in +url_for+ calls.
+
+If you define +default_url_options+ in +ApplicationController+, as in the example above, it would be used for all URL generation. The method can also be defined in one specific controller, in which case it only affects URLs generated there.
h3. Session
diff --git a/guides/source/action_view_overview.textile b/guides/source/action_view_overview.textile
index 42120e9bad..6649974eea 100644
--- a/guides/source/action_view_overview.textile
+++ b/guides/source/action_view_overview.textile
@@ -550,9 +550,9 @@ Register one or more JavaScript files to be included when symbol is passed to ja
ActionView::Helpers::AssetTagHelper.register_javascript_expansion :monkey => ["head", "body", "tail"]
javascript_include_tag :monkey # =>
- <script type="text/javascript" src="/javascripts/head.js"></script>
- <script type="text/javascript" src="/javascripts/body.js"></script>
- <script type="text/javascript" src="/javascripts/tail.js"></script>
+ <script src="/javascripts/head.js"></script>
+ <script src="/javascripts/body.js"></script>
+ <script src="/javascripts/tail.js"></script>
</ruby>
h5. register_stylesheet_expansion
@@ -563,9 +563,9 @@ Register one or more stylesheet files to be included when symbol is passed to +s
ActionView::Helpers::AssetTagHelper.register_stylesheet_expansion :monkey => ["head", "body", "tail"]
stylesheet_link_tag :monkey # =>
- <link href="/stylesheets/head.css" media="screen" rel="stylesheet" type="text/css" />
- <link href="/stylesheets/body.css" media="screen" rel="stylesheet" type="text/css" />
- <link href="/stylesheets/tail.css" media="screen" rel="stylesheet" type="text/css" />
+ <link href="/stylesheets/head.css" media="screen" rel="stylesheet" />
+ <link href="/stylesheets/body.css" media="screen" rel="stylesheet" />
+ <link href="/stylesheets/tail.css" media="screen" rel="stylesheet" />
</ruby>
h5. auto_discovery_link_tag
@@ -607,7 +607,7 @@ Returns an html script tag for each of the sources provided. You can pass in the
<ruby>
javascript_include_tag "common" # =>
- <script type="text/javascript" src="/javascripts/common.js"></script>
+ <script src="/javascripts/common.js"></script>
</ruby>
If the application does not use the asset pipeline, to include the jQuery JavaScript library in your application, pass +:defaults+ as the source. When using +:defaults+, if an +application.js+ file exists in your +public/javascripts+ directory, it will be included as well.
@@ -626,7 +626,7 @@ You can also cache multiple JavaScript files into one file, which requires less
<ruby>
javascript_include_tag :all, :cache => true # =>
- <script type="text/javascript" src="/javascripts/all.js"></script>
+ <script src="/javascripts/all.js"></script>
</ruby>
h5. javascript_path
@@ -651,7 +651,7 @@ Returns a stylesheet link tag for the sources specified as arguments. If you don
<ruby>
stylesheet_link_tag "application" # =>
- <link href="/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />
+ <link href="/stylesheets/application.css" media="screen" rel="stylesheet" />
</ruby>
You can also include all styles in the stylesheet directory using :all as the source:
@@ -664,7 +664,7 @@ You can also cache multiple stylesheets into one file, which requires less HTTP
<ruby>
stylesheet_link_tag :all, :cache => true
- <link href="/stylesheets/all.css" media="screen" rel="stylesheet" type="text/css" />
+ <link href="/stylesheets/all.css" media="screen" rel="stylesheet" />
</ruby>
h5. stylesheet_path
@@ -805,7 +805,7 @@ For example, let's say we have a standard application layout, but also a special
<p>This is a special page.</p>
<% content_for :special_script do %>
- <script type="text/javascript">alert('Hello!')</script>
+ <script>alert('Hello!')</script>
<% end %>
</ruby>
@@ -1501,7 +1501,7 @@ javascript_tag "alert('All is good')"
</ruby>
<html>
-<script type="text/javascript">
+<script>
//<![CDATA[
alert('All is good')
//]]>
diff --git a/guides/source/active_record_querying.textile b/guides/source/active_record_querying.textile
index 8e23a577e2..902ceeb78b 100644
--- a/guides/source/active_record_querying.textile
+++ b/guides/source/active_record_querying.textile
@@ -133,6 +133,24 @@ SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1
<tt>Model.last</tt> returns +nil+ if no matching record is found. No exception will be raised.
+h5. +find_by+
+
+<tt>Model.find_by</tt> finds the first record matching some conditions. For example:
+
+<ruby>
+Client.find_by first_name: 'Lifo'
+# => #<Client id: 1, first_name: "Lifo">
+
+Client.find_by first_name: 'Jon'
+# => nil
+</ruby>
+
+It is equivalent to writing:
+
+<ruby>
+Client.where(first_name: 'Lifo').first
+</ruby>
+
h5(#first_1). +first!+
<tt>Model.first!</tt> finds the first record. For example:
@@ -167,6 +185,24 @@ SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1
<tt>Model.last!</tt> raises +RecordNotFound+ if no matching record is found.
+h5(#find_by_1). +find_by!+
+
+<tt>Model.find_by!</tt> finds the first record matching some conditions. It raises +RecordNotFound+ if no matching record is found. For example:
+
+<ruby>
+Client.find_by! first_name: 'Lifo'
+# => #<Client id: 1, first_name: "Lifo">
+
+Client.find_by! first_name: 'Jon'
+# => RecordNotFound
+</ruby>
+
+It is equivalent to writing:
+
+<ruby>
+Client.where(first_name: 'Lifo').first!
+</ruby>
+
h4. Retrieving Multiple Objects
h5. Using Multiple Primary Keys
@@ -320,20 +356,6 @@ Client.where("created_at >= :start_date AND created_at <= :end_date",
This makes for clearer readability if you have a large number of variable conditions.
-h5(#array-range_conditions). Range Conditions
-
-If you're looking for a range inside of a table (for example, users created in a certain timeframe) you can use the conditions option coupled with the +IN+ SQL statement for this. If you had two dates coming in from a controller you could do something like this to look for a range:
-
-<ruby>
-Client.where(:created_at => (params[:start_date].to_date)..(params[:end_date].to_date))
-</ruby>
-
-This query will generate something similar to the following SQL:
-
-<sql>
- SELECT "clients".* FROM "clients" WHERE ("clients"."created_at" BETWEEN '2010-09-29' AND '2010-11-30')
-</sql>
-
h4. Hash Conditions
Active Record also allows you to pass in hash conditions which can increase the readability of your conditions syntax. With hash conditions, you pass in a hash with keys of the fields you want conditionalised and the values of how you want to conditionalise them:
@@ -352,9 +374,9 @@ The field name can also be a string:
Client.where('locked' => true)
</ruby>
-h5(#hash-range_conditions). Range Conditions
+NOTE: The values cannot be symbols. For example, you cannot do +Client.where(:status => :active)+.
-The good thing about this is that we can pass in a range for our fields without it generating a large query as shown in the preamble of this section.
+h5(#hash-range_conditions). Range Conditions
<ruby>
Client.where(:created_at => (Time.now.midnight - 1.day)..Time.now.midnight)
@@ -503,7 +525,9 @@ And this will give you a single +Order+ object for each date where there are ord
The SQL that would be executed would be something like this:
<sql>
-SELECT date(created_at) as ordered_date, sum(price) as total_price FROM orders GROUP BY date(created_at)
+SELECT date(created_at) as ordered_date, sum(price) as total_price
+FROM orders
+GROUP BY date(created_at)
</sql>
h3. Having
@@ -519,7 +543,10 @@ Order.select("date(created_at) as ordered_date, sum(price) as total_price").grou
The SQL that would be executed would be something like this:
<sql>
-SELECT date(created_at) as ordered_date, sum(price) as total_price FROM orders GROUP BY date(created_at) HAVING sum(price) > 100
+SELECT date(created_at) as ordered_date, sum(price) as total_price
+FROM orders
+GROUP BY date(created_at)
+HAVING sum(price) > 100
</sql>
This will return single order objects for each day, but only those that are ordered more than $100 in a day.
@@ -659,7 +686,7 @@ Optimistic locking allows multiple users to access the same record for edits, an
<strong>Optimistic locking column</strong>
-In order to use optimistic locking, the table needs to have a column called +lock_version+. Each time the record is updated, Active Record increments the +lock_version+ column. If an update request is made with a lower value in the +lock_version+ field than is currently in the +lock_version+ column in the database, the update request will fail with an +ActiveRecord::StaleObjectError+. Example:
+In order to use optimistic locking, the table needs to have a column called +lock_version+ of type integer. Each time the record is updated, Active Record increments the +lock_version+ column. If an update request is made with a lower value in the +lock_version+ field than is currently in the +lock_version+ column in the database, the update request will fail with an +ActiveRecord::StaleObjectError+. Example:
<ruby>
c1 = Client.find(1)
@@ -793,7 +820,7 @@ SELECT categories.* FROM categories
INNER JOIN posts ON posts.category_id = categories.id
</sql>
-Or, in English: "return a Category object for all categories with posts". Note that you will see duplicate categories if more than one post has the same category. If you want unique categories, you can use Category.joins(:post).select("distinct(categories.id)").
+Or, in English: "return a Category object for all categories with posts". Note that you will see duplicate categories if more than one post has the same category. If you want unique categories, you can use Category.joins(:posts).select("distinct(categories.id)").
h5. Joining Multiple Associations
@@ -943,21 +970,23 @@ If, in the case of this +includes+ query, there were no comments for any posts,
h3. Scopes
-Scoping allows you to specify commonly-used ARel queries which can be referenced as method calls on the association objects or models. With these scopes, you can use every method previously covered such as +where+, +joins+ and +includes+. All scope methods will return an +ActiveRecord::Relation+ object which will allow for further methods (such as other scopes) to be called on it.
+Scoping allows you to specify commonly-used queries which can be referenced as method calls on the association objects or models. With these scopes, you can use every method previously covered such as +where+, +joins+ and +includes+. All scope methods will return an +ActiveRecord::Relation+ object which will allow for further methods (such as other scopes) to be called on it.
-To define a simple scope, we use the +scope+ method inside the class, passing the ARel query that we'd like run when this scope is called:
+To define a simple scope, we use the +scope+ method inside the class, passing the query that we'd like run when this scope is called:
<ruby>
class Post < ActiveRecord::Base
- scope :published, where(:published => true)
+ scope :published, -> { where(published: true) }
end
</ruby>
-Just like before, these methods are also chainable:
+This is exactly the same as defining a class method, and which you use is a matter of personal preference:
<ruby>
class Post < ActiveRecord::Base
- scope :published, where(:published => true).joins(:category)
+ def self.published
+ where(published: true)
+ end
end
</ruby>
@@ -965,8 +994,8 @@ Scopes are also chainable within scopes:
<ruby>
class Post < ActiveRecord::Base
- scope :published, where(:published => true)
- scope :published_and_commented, published.and(self.arel_table[:comments_count].gt(0))
+ scope :published, -> { where(:published => true) }
+ scope :published_and_commented, -> { published.where("comments_count > 0") }
end
</ruby>
@@ -983,25 +1012,13 @@ category = Category.first
category.posts.published # => [published posts belonging to this category]
</ruby>
-h4. Working with times
-
-If you're working with dates or times within scopes, due to how they are evaluated, you will need to use a lambda so that the scope is evaluated every time.
-
-<ruby>
-class Post < ActiveRecord::Base
- scope :created_before_now, lambda { where("created_at < ?", Time.zone.now ) }
-end
-</ruby>
-
-Without the +lambda+, this +Time.zone.now+ will only be called once.
-
h4. Passing in arguments
-When a +lambda+ is used for a +scope+, it can take arguments:
+Your scope can take arguments:
<ruby>
class Post < ActiveRecord::Base
- scope :created_before, lambda { |time| where("created_at < ?", time) }
+ scope :created_before, ->(time) { where("created_at < ?", time) }
end
</ruby>
@@ -1048,7 +1065,7 @@ If we wish for a scope to be applied across all queries to the model we can use
<ruby>
class Client < ActiveRecord::Base
- default_scope where("removed_at IS NULL")
+ default_scope { where("removed_at IS NULL") }
end
</ruby>
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/api_documentation_guidelines.textile b/guides/source/api_documentation_guidelines.textile
index 93120c15a7..c6aa1f0a2b 100644
--- a/guides/source/api_documentation_guidelines.textile
+++ b/guides/source/api_documentation_guidelines.textile
@@ -6,7 +6,7 @@ endprologue.
h3. RDoc
-The Rails API documentation is generated with RDoc 2.5. Please consult the documentation for help with the "markup":http://rdoc.rubyforge.org/RDoc/Markup.html, and take into account also these "additional directives":http://rdoc.rubyforge.org/RDoc/Parser/Ruby.html.
+The Rails API documentation is generated with RDoc. Please consult the documentation for help with the "markup":http://rdoc.rubyforge.org/RDoc/Markup.html, and also take into account these "additional directives":http://rdoc.rubyforge.org/RDoc/Parser/Ruby.html.
h3. Wording
@@ -14,7 +14,7 @@ Write simple, declarative sentences. Brevity is a plus: get to the point.
Write in present tense: "Returns a hash that...", rather than "Returned a hash that..." or "Will return a hash that...".
-Start comments in upper case, follow regular punctuation rules:
+Start comments in upper case. Follow regular punctuation rules:
<ruby>
# Declares an attribute reader backed by an internally-named instance variable.
@@ -23,7 +23,7 @@ def attr_internal_reader(*attrs)
end
</ruby>
-Communicate to the reader the current way of doing things, both explicitly and implicitly. Use the recommended idioms in edge, reorder sections to emphasize favored approaches if needed, etc. The documentation should be a model for best practices and canonical, modern Rails usage.
+Communicate to the reader the current way of doing things, both explicitly and implicitly. Use the idioms recommended in edge. Reorder sections to emphasize favored approaches if needed, etc. The documentation should be a model for best practices and canonical, modern Rails usage.
Documentation has to be concise but comprehensive. Explore and document edge cases. What happens if a module is anonymous? What if a collection is empty? What if an argument is nil?
@@ -41,10 +41,9 @@ h3. Example Code
Choose meaningful examples that depict and cover the basics as well as interesting points or gotchas.
-Use two spaces to indent chunks of code--that is two spaces with respect to the left margin; the examples
-themselves should use "Rails coding conventions":contributing_to_ruby_on_rails.html#follow-the-coding-conventions.
+Use two spaces to indent chunks of code--that is, for markup purposes, two spaces with respect to the left margin. The examples themselves should use "Rails coding conventions":contributing_to_ruby_on_rails.html#follow-the-coding-conventions.
-Short docs do not need an explicit "Examples" label to introduce snippets, they just follow paragraphs:
+Short docs do not need an explicit "Examples" label to introduce snippets; they just follow paragraphs:
<ruby>
# Converts a collection of elements into a formatted string by calling
@@ -64,7 +63,7 @@ On the other hand, big chunks of structured documentation may have a separate "E
# Person.exists?(['name LIKE ?', "%#{query}%"])
</ruby>
-The result of expressions follow them and are introduced by "# => ", vertically aligned:
+The results of expressions follow them and are introduced by "# => ", vertically aligned:
<ruby>
# For checking if a fixnum is even or odd.
@@ -98,7 +97,7 @@ On the other hand, regular comments do not use an arrow:
h3. Filenames
-As a rule of thumb use filenames relative to the application root:
+As a rule of thumb, use filenames relative to the application root:
<plain>
config/routes.rb # YES
@@ -111,12 +110,12 @@ h3. Fonts
h4. Fixed-width Font
Use fixed-width fonts for:
-* constants, in particular class and module names
-* method names
-* literals like +nil+, +false+, +true+, +self+
-* symbols
-* method parameters
-* file names
+* Constants, in particular class and module names.
+* Method names.
+* Literals like +nil+, +false+, +true+, +self+.
+* Symbols.
+* Method parameters.
+* File names.
<ruby>
class Array
@@ -134,6 +133,20 @@ h4. Regular Font
When "true" and "false" are English words rather than Ruby keywords use a regular font:
+<ruby>
+# Runs all the validations within the specified context. Returns true if no errors are found,
+# false otherwise.
+#
+# If the argument is false (default is +nil+), the context is set to <tt>:create</tt> if
+# <tt>new_record?</tt> is true, and to <tt>:update</tt> if it is not.
+#
+# Validations with no <tt>:on</tt> option will run no matter the context. Validations with
+# some <tt>:on</tt> option will only run in the specified context.
+def valid?(context = nil)
+ ...
+end
+</ruby>
+
h3. Description Lists
In lists of options, parameters, etc. use a hyphen between the item and its description (reads better than a colon because normally options are symbols):
@@ -146,7 +159,7 @@ The description starts in upper case and ends with a full stop—it's standard E
h3. Dynamically Generated Methods
-Methods created with +(module|class)_eval(STRING)+ have a comment by their side with an instance of the generated code. That comment is 2 spaces apart from the template:
+Methods created with +(module|class)_eval(STRING)+ have a comment by their side with an instance of the generated code. That comment is 2 spaces away from the template:
<ruby>
for severity in Severity.constants
@@ -162,7 +175,7 @@ for severity in Severity.constants
end
</ruby>
-If the resulting lines are too wide, say 200 columns or more, we put the comment above the call:
+If the resulting lines are too wide, say 200 columns or more, put the comment above the call:
<ruby>
# def self.find_by_login_and_activated(*args)
diff --git a/guides/source/asset_pipeline.textile b/guides/source/asset_pipeline.textile
index b1b1d21c2d..d79eb01ab2 100644
--- a/guides/source/asset_pipeline.textile
+++ b/guides/source/asset_pipeline.textile
@@ -328,9 +328,9 @@ This manifest +app/assets/javascripts/application.js+:
would generate this HTML:
<html>
-<script src="/assets/core.js?body=1" type="text/javascript"></script>
-<script src="/assets/projects.js?body=1" type="text/javascript"></script>
-<script src="/assets/tickets.js?body=1" type="text/javascript"></script>
+<script src="/assets/core.js?body=1"></script>
+<script src="/assets/projects.js?body=1"></script>
+<script src="/assets/tickets.js?body=1"></script>
</html>
The +body+ param is required by Sprockets.
@@ -346,7 +346,7 @@ config.assets.debug = false
When debug mode is off, Sprockets concatenates and runs the necessary preprocessors on all files. With debug mode turned off the manifest above would generate instead:
<html>
-<script src="/assets/application.js" type="text/javascript"></script>
+<script src="/assets/application.js"></script>
</html>
Assets are compiled and cached on the first request after the server is started. Sprockets sets a +must-revalidate+ Cache-Control HTTP header to reduce request overhead on subsequent requests -- on these the browser gets a 304 (Not Modified) response.
@@ -380,8 +380,8 @@ For example this:
generates something like this:
<html>
-<script src="/assets/application-908e25f4bf641868d8683022a5b62f54.js" type="text/javascript"></script>
-<link href="/assets/application-4dd5b109ee3439da54f5bdfd78a80473.css" media="screen" rel="stylesheet" type="text/css" />
+<script src="/assets/application-908e25f4bf641868d8683022a5b62f54.js"></script>
+<link href="/assets/application-4dd5b109ee3439da54f5bdfd78a80473.css" media="screen" rel="stylesheet" />
</html>
The fingerprinting behavior is controlled by the setting of +config.assets.digest+ setting in Rails (which defaults to +true+ for production and +false+ for everything else).
@@ -409,7 +409,9 @@ cannot see application objects or methods. *Heroku requires this to be false.*
WARNING: If you set +config.assets.initialize_on_precompile+ to false, be sure to
test +rake assets:precompile+ locally before deploying. It may expose bugs where
your assets reference application objects or methods, since those are still
-in scope in development mode regardless of the value of this flag.
+in scope in development mode regardless of the value of this flag. Changing this flag also affects
+engines. Engines can define assets for precompilation as well. Since the complete environment is not loaded,
+engines (or other gems) will not be loaded, which can cause missing assets.
Capistrano (v2.8.0 and above) includes a recipe to handle this in deployment. Add the following line to +Capfile+:
@@ -671,7 +673,7 @@ config.assets.compile = false
# Generate digests for assets URLs.
config.assets.digest = true
-# Defaults to Rails.root.join("public/assets")
+# Defaults to nil and saved in location specified by config.assets.prefix
# config.assets.manifest = YOUR_PATH
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
diff --git a/guides/source/association_basics.textile b/guides/source/association_basics.textile
index 493b7c30be..8ddc56bef1 100644
--- a/guides/source/association_basics.textile
+++ b/guides/source/association_basics.textile
@@ -342,9 +342,9 @@ In designing a data model, you will sometimes find a model that should have a re
<ruby>
class Employee < ActiveRecord::Base
- has_many :subordinates, :class_name => "Employee"
- belongs_to :manager, :class_name => "Employee",
+ has_many :subordinates, :class_name => "Employee",
:foreign_key => "manager_id"
+ belongs_to :manager, :class_name => "Employee"
end
</ruby>
diff --git a/guides/source/caching_with_rails.textile b/guides/source/caching_with_rails.textile
index e2c6c7a2a4..12bc32f4e1 100644
--- a/guides/source/caching_with_rails.textile
+++ b/guides/source/caching_with_rails.textile
@@ -92,7 +92,7 @@ INFO: Page caching runs in an after filter. Thus, invalid requests won't generat
h4. Action Caching
-One of the issues with Page Caching is that you cannot use it for pages that require to restrict access somehow. This is where Action Caching comes in. Action Caching works like Page Caching except for the fact that the incoming web request does go from the webserver to the Rails stack and Action Pack so that before filters can be run on it before the cache is served. This allows authentication and other restriction to be run while still serving the result of the output from a cached copy.
+Page Caching cannot be used for actions that have before filters - for example, pages that require authentication. This is where Action Caching comes in. Action Caching works like Page Caching except the incoming web request hits the Rails stack so that before filters can be run on it before the cache is served. This allows authentication and other restrictions to be run while still serving the result of the output from a cached copy.
Clearing the cache works in a similar way to Page Caching, except you use +expire_action+ instead of +expire_page+.
@@ -257,7 +257,9 @@ However, it's important to note that query caches are created at the start of an
h3. Cache Stores
-Rails provides different stores for the cached data created by action and fragment caches. Page caches are always stored on disk.
+Rails provides different stores for the cached data created by <b>action</b> and <b>fragment</b> caches.
+
+TIP: Page caches are always stored on disk.
h4. Configuration
@@ -267,7 +269,7 @@ You can set up your application's default cache store by calling +config.cache_s
config.cache_store = :memory_store
</ruby>
-Alternatively, you can call +ActionController::Base.cache_store+ outside of a configuration block.
+NOTE: Alternatively, you can call +ActionController::Base.cache_store+ outside of a configuration block.
You can access the cache by calling +Rails.cache+.
@@ -294,7 +296,7 @@ h4. ActiveSupport::Cache::MemoryStore
This cache store keeps entries in memory in the same Ruby process. The cache store has a bounded size specified by the +:size+ options to the initializer (default is 32Mb). When the cache exceeds the allotted size, a cleanup will occur and the least recently used entries will be removed.
<ruby>
-ActionController::Base.cache_store = :memory_store, :size => 64.megabytes
+config.cache_store = :memory_store, :size => 64.megabytes
</ruby>
If you're running multiple Ruby on Rails server processes (which is the case if you're using mongrel_cluster or Phusion Passenger), then your Rails server process instances won't be able to share cache data with each other. This cache store is not appropriate for large application deployments, but can work well for small, low traffic sites with only a couple of server processes or for development and test environments.
@@ -306,7 +308,7 @@ h4. ActiveSupport::Cache::FileStore
This cache store uses the file system to store entries. The path to the directory where the store files will be stored must be specified when initializing the cache.
<ruby>
-ActionController::Base.cache_store = :file_store, "/path/to/cache/directory"
+config.cache_store = :file_store, "/path/to/cache/directory"
</ruby>
With this cache store, multiple server processes on the same host can share a cache. Servers processes running on different hosts could share a cache by using a shared file system, but that set up would not be ideal and is not recommended. The cache store is appropriate for low to medium traffic sites that are served off one or two hosts.
@@ -322,7 +324,7 @@ When initializing the cache, you need to specify the addresses for all memcached
The +write+ and +fetch+ methods on this cache accept two additional options that take advantage of features specific to memcached. You can specify +:raw+ to send a value directly to the server with no serialization. The value must be a string or number. You can use memcached direct operation like +increment+ and +decrement+ only on raw values. You can also specify +:unless_exist+ if you don't want memcached to overwrite an existing entry.
<ruby>
-ActionController::Base.cache_store = :mem_cache_store, "cache-1.example.com", "cache-2.example.com"
+config.cache_store = :mem_cache_store, "cache-1.example.com", "cache-2.example.com"
</ruby>
h4. ActiveSupport::Cache::EhcacheStore
@@ -330,7 +332,7 @@ h4. ActiveSupport::Cache::EhcacheStore
If you are using JRuby you can use Terracotta's Ehcache as the cache store for your application. Ehcache is an open source Java cache that also offers an enterprise version with increased scalability, management, and commercial support. You must first install the jruby-ehcache-rails3 gem (version 1.1.0 or later) to use this cache store.
<ruby>
-ActionController::Base.cache_store = :ehcache_store
+config.cache_store = :ehcache_store
</ruby>
When initializing the cache, you may use the +:ehcache_config+ option to specify the Ehcache config file to use (where the default is "ehcache.xml" in your Rails config directory), and the :cache_name option to provide a custom name for your cache (the default is rails_cache).
@@ -359,7 +361,7 @@ h4. ActiveSupport::Cache::NullStore
This cache store implementation is meant to be used only in development or test environments and it never stores anything. This can be very useful in development when you have code that interacts directly with +Rails.cache+, but caching may interfere with being able to see the results of code changes. With this cache store, all +fetch+ and +read+ operations will result in a miss.
<ruby>
-ActionController::Base.cache_store = :null_store
+config.cache_store = :null_store
</ruby>
h4. Custom Cache Stores
@@ -369,7 +371,7 @@ You can create your own custom cache store by simply extending +ActiveSupport::C
To use a custom cache store, simple set the cache store to a new instance of the class.
<ruby>
-ActionController::Base.cache_store = MyCacheStore.new
+config.cache_store = MyCacheStore.new
</ruby>
h4. Cache Keys
diff --git a/guides/source/command_line.textile b/guides/source/command_line.textile
index 463c2b172b..858ce47db1 100644
--- a/guides/source/command_line.textile
+++ b/guides/source/command_line.textile
@@ -278,6 +278,12 @@ The +console+ command lets you interact with your Rails application from the com
You can also use the alias "c" to invoke the console: <tt>rails c</tt>.
+You can specify the environment in which the +console+ command should operate using the +-e+ switch.
+
+<shell>
+$ rails console -e staging
+</shell>
+
If you wish to test out some code without changing any data, you can do that by invoking +rails console --sandbox+.
<shell>
diff --git a/guides/source/configuring.textile b/guides/source/configuring.textile
index cf0d8f1a43..68426221bf 100644
--- a/guides/source/configuring.textile
+++ b/guides/source/configuring.textile
@@ -354,8 +354,7 @@ h4. Configuring Action Dispatch
h4. Configuring Action View
-There are only a few configuration options for Action View, starting with six on +ActionView::Base+:
-
+<tt>config.action_view</tt> includes a small number of configuration settings:
* +config.action_view.field_error_proc+ provides an HTML generator for displaying errors that come from Active Record. The default is
@@ -363,7 +362,7 @@ There are only a few configuration options for Action View, starting with six on
Proc.new { |html_tag, instance| %Q(<div class="field_with_errors">#{html_tag}</div>).html_safe }
</ruby>
-* +config.action_view.default_form_builder+ tells Rails which form builder to use by default. The default is +ActionView::Helpers::FormBuilder+.
+* +config.action_view.default_form_builder+ tells Rails which form builder to use by default. The default is +ActionView::Helpers::FormBuilder+. If you want your form builder class to be loaded after initialization (so it's reloaded on each request in development), you can pass it as a +String+
* +config.action_view.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby Logger class, which is then used to log information from Action View. Set to +nil+ to disable logging.
@@ -395,6 +394,16 @@ And can reference in the view with the following code:
* +config.action_view.cache_asset_ids+ With the cache enabled, the asset tag helper methods will make fewer expensive file system calls (the default implementation checks the file system timestamp). However this prevents you from modifying any asset files while the server is running.
+* +config.action_view.embed_authenticity_token_in_remote_forms+ allows you to set the default behavior for +authenticity_token+ in forms with +:remote => true+. By default it's set to false, which means that remote forms will not include +authenticity_token+, which is helpful when you're fragment-caching the form. Remote forms get the authenticity from the +meta+ tag, so embedding is unnecessary unless you support browsers without JavaScript. In such case you can either pass +:authenticity_token => true+ as a form option or set this config setting to +true+
+
+* +config.action_view.prefix_partial_path_with_controller_namespace+ determines whether or not partials are looked up from a subdirectory in templates rendered from namespaced controllers. For example, consider a controller named +Admin::PostsController+ which renders this template:
+
+<erb>
+<%= render @post %>
+<erb>
+
+The default setting is +true+, which uses the partial at +/admin/posts/_post.erb+. Setting the value to +false+ would render +/posts/_post.erb+, which is the same behavior as rendering from a non-namespaced controller such as +PostsController+.
+
h4. Configuring Action Mailer
There are a number of settings available on +config.action_mailer+:
@@ -516,6 +525,14 @@ development:
password:
</yaml>
+Prepared Statements can be disabled thus:
+
+<yaml>
+production:
+ adapter: postgresql
+ prepared_statements: false
+</yaml>
+
h5. Configuring an SQLite3 Database for JRuby Platform
If you choose to use SQLite3 and are using JRuby, your +config/database.yml+ will look a little different. Here's the development section:
diff --git a/guides/source/contributing_to_ruby_on_rails.textile b/guides/source/contributing_to_ruby_on_rails.textile
index df8b16eb9e..fbb3483dae 100644
--- a/guides/source/contributing_to_ruby_on_rails.textile
+++ b/guides/source/contributing_to_ruby_on_rails.textile
@@ -8,29 +8,29 @@ This guide covers ways in which _you_ can become a part of the ongoing developme
* Contributing to the Ruby on Rails documentation
* Contributing to the Ruby on Rails code
-Ruby on Rails is not "someone else's framework." Over the years, hundreds of people have contributed to Ruby on Rails ranging from a single character to massive architectural changes or significant documentation. All with the goal of making Ruby on Rails better for everyone. Even if you don't feel up to writing code or documentation yet, there are a variety of other ways that you can contribute, from reporting issues to testing patches.
+Ruby on Rails is not "someone else's framework." Over the years, hundreds of people have contributed to Ruby on Rails ranging from a single character to massive architectural changes or significant documentation -- all with the goal of making Ruby on Rails better for everyone. Even if you don't feel up to writing code or documentation yet, there are a variety of other ways that you can contribute, from reporting issues to testing patches.
endprologue.
h3. Reporting an Issue
-Ruby on Rails uses "GitHub Issue Tracking":https://github.com/rails/rails/issues to track issues (primarily bugs and contributions of new code). If you've found a bug in Ruby on Rails, this is the place to start. You'll need to create a (free) GitHub account in order to either submit an issue, comment on them or create pull requests.
+Ruby on Rails uses "GitHub Issue Tracking":https://github.com/rails/rails/issues to track issues (primarily bugs and contributions of new code). If you've found a bug in Ruby on Rails, this is the place to start. You'll need to create a (free) GitHub account in order to submit an issue, to comment on them or to create pull requests.
NOTE: Bugs in the most recent released version of Ruby on Rails are likely to get the most attention. Also, the Rails core team is always interested in feedback from those who can take the time to test _edge Rails_ (the code for the version of Rails that is currently under development). Later in this guide you'll find out how to get edge Rails for testing.
h4. Creating a Bug Report
-If you've found a problem in Ruby on Rails which is not a security risk do a search in GitHub Issues in case it was already reported. If you find no issue addressing it you can "add a new one":https://github.com/rails/rails/issues/new. (See the next section for reporting security issues.)
+If you've found a problem in Ruby on Rails which is not a security risk, do a search in GitHub under "Issues":https://github.com/rails/rails/issues in case it was already reported. If you find no issue addressing it you can "add a new one":https://github.com/rails/rails/issues/new. (See the next section for reporting security issues.)
-At the minimum, your issue report needs a title and descriptive text. But that's only a minimum. You should include as much relevant information as possible. You need to at least post the code sample that has the issue. Even better is to include a unit test that shows how the expected behavior is not occurring. Your goal should be to make it easy for yourself - and others - to replicate the bug and figure out a fix.
+At the minimum, your issue report needs a title and descriptive text. But that's only a minimum. You should include as much relevant information as possible. You need at least to post the code sample that has the issue. Even better is to include a unit test that shows how the expected behavior is not occurring. Your goal should be to make it easy for yourself -- and others -- to replicate the bug and figure out a fix.
-Then don't get your hopes up. Unless you have a "Code Red, Mission Critical, The World is Coming to an End" kind of bug, you're creating this issue report in the hope that others with the same problem will be able to collaborate with you on solving it. Do not expect that the issue report will automatically see any activity or that others will jump to fix it. Creating an issue like this is mostly to help yourself start on the path of fixing the problem and for others to confirm it with a "I'm having this problem too" comment.
+Then, don't get your hopes up! Unless you have a "Code Red, Mission Critical, the World is Coming to an End" kind of bug, you're creating this issue report in the hope that others with the same problem will be able to collaborate with you on solving it. Do not expect that the issue report will automatically see any activity or that others will jump to fix it. Creating an issue like this is mostly to help yourself start on the path of fixing the problem and for others to confirm it with an "I'm having this problem too" comment.
h4. Special Treatment for Security Issues
WARNING: Please do not report security vulnerabilities with public GitHub issue reports. The "Rails security policy page":http://rubyonrails.org/security details the procedure to follow for security issues.
-h4. What About Feature Requests?
+h4. What about Feature Requests?
Please don't put "feature request" items into GitHub Issues. If there's a new feature that you want to see added to Ruby on Rails, you'll need to write the code yourself - or convince someone else to partner with you to write the code. Later in this guide you'll find detailed instructions for proposing a patch to Ruby on Rails. If you enter a wishlist item in GitHub Issues with no code, you can expect it to be marked "invalid" as soon as it's reviewed.
@@ -38,11 +38,11 @@ h3. Running the Test Suite
To move on from submitting bugs to helping resolve existing issues or contributing your own code to Ruby on Rails, you _must_ be able to run its test suite. In this section of the guide you'll learn how to set up the tests on your own computer.
-h4. Install git
+h4. Install Git
Ruby on Rails uses git for source code control. The "git homepage":http://git-scm.com/ has installation instructions. There are a variety of resources on the net that will help you get familiar with git:
-* "Everyday Git":http://www.kernel.org/pub/software/scm/git/docs/everyday.html will teach you just enough about git to get by.
+* "Everyday Git":http://schacon.github.com/git/everyday.html will teach you just enough about git to get by.
* The "PeepCode screencast":https://peepcode.com/products/git on git ($9) is easier to follow.
* "GitHub":http://help.github.com offers links to a variety of git resources.
* "Pro Git":http://progit.org/book/ is an entire book about git with a Creative Commons license.
@@ -66,7 +66,7 @@ Install first libxml2 and libxslt together with their development files for Noko
$ sudo apt-get install libxml2 libxml2-dev libxslt1-dev
</shell>
-Also, SQLite3 and its development files for the +sqlite3-ruby+ gem, in Ubuntu you're done with
+Also, SQLite3 and its development files for the +sqlite3-ruby+ gem -- in Ubuntu you're done with just
<shell>
$ sudo apt-get install sqlite3 libsqlite3-dev
@@ -76,6 +76,7 @@ Get a recent version of "Bundler":http://gembundler.com/:
<shell>
$ gem install bundler
+$ gem update bundler
</shell>
and run:
@@ -84,20 +85,20 @@ and run:
$ bundle install --without db
</shell>
-This command will install all dependencies except the MySQL and PostgreSQL Ruby drivers. We will come back at these soon. With dependencies installed, you can run the test suite with:
+This command will install all dependencies except the MySQL and PostgreSQL Ruby drivers. We will come back to these soon. With dependencies installed, you can run the test suite with:
<shell>
$ bundle exec rake test
</shell>
-You can also run tests for a specific framework, like Action Pack, by going into its directory and executing the same command:
+You can also run tests for a specific component, like Action Pack, by going into its directory and executing the same command:
<shell>
$ cd actionpack
$ bundle exec rake test
</shell>
-If you want to run tests from the specific directory use the +TEST_DIR+ environment variable. For example, this will run tests inside +railties/test/generators+ directory only:
+If you want to run the tests located in a specific directory use the +TEST_DIR+ environment variable. For example, this will run the tests of the +railties/test/generators+ directory only:
<shell>
$ cd railties
@@ -106,9 +107,9 @@ $ TEST_DIR=generators bundle exec rake test
h4. Warnings
-The test suite runs with warnings enabled. Ideally Ruby on Rails should issue no warning, but there may be a few, and also some from third-party libraries. Please ignore (or fix!) them if any, and submit patches that do not issue new 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.
-As of this writing they are specially noisy with Ruby 1.9. If you are sure about what you are doing and would like to have a more clear output, there's a way to override the flag:
+As of this writing (December, 2010) they are specially noisy with Ruby 1.9. If you are sure about what you are doing and would like to have a more clear output, there's a way to override the flag:
<shell>
$ RUBYOPT=-W0 bundle exec rake test
@@ -116,17 +117,17 @@ $ RUBYOPT=-W0 bundle exec rake test
h4. Testing Active Record
-The test suite of Active Record attempts to run four times, once for SQLite3, once for each of the two MySQL gems (+mysql+ and +mysql2+), and once for PostgreSQL. We are going to see now how to setup the environment for them.
+The test suite of Active Record attempts to run four times: once for SQLite3, once for each of the two MySQL gems (+mysql+ and +mysql2+), and once for PostgreSQL. We are going to see now how to set up the environment for them.
WARNING: If you're working with Active Record code, you _must_ ensure that the tests pass for at least MySQL, PostgreSQL, and SQLite3. Subtle differences between the various adapters have been behind the rejection of many patches that looked OK when tested only against MySQL.
-h5. Set up Database Configuration
+h5. Database Configuration
The Active Record test suite requires a custom config file: +activerecord/test/config.yml+. An example is provided in +activerecord/test/config.example.yml+ which can be copied and used as needed for your environment.
h5. SQLite3
-The gem +sqlite3-ruby+ does not belong to the "db" group indeed, if you followed the instructions above you're ready. This is how you run the Active Record test suite only for SQLite3:
+The gem +sqlite3-ruby+ does not belong to the "db" group. Indeed, if you followed the instructions above you're ready. This is how you run the Active Record test suite only for SQLite3:
<shell>
$ cd activerecord
@@ -167,13 +168,13 @@ $ cd activerecord
$ rake mysql:build_databases
</shell>
-PostgreSQL's authentication works differently. A simple way to setup the development environment for example is to run with your development account
+PostgreSQL's authentication works differently. A simple way to set up the development environment for example is to run with your development account
<shell>
$ sudo -u postgres createuser --superuser $USER
</shell>
-and after that create the test databases with
+and then create the test databases with
<shell>
$ cd activerecord
@@ -182,9 +183,9 @@ $ rake postgresql:build_databases
NOTE: Using the rake task to create the test databases ensures they have the correct character set and collation.
-If you’re using another database, check the files under +activerecord/test/connections+ for default connection information. You can edit these files if you _must_ on your machine to provide different credentials, but obviously you should not push any such changes back to Rails.
+If you’re using another database, check the files under +activerecord/test/connections+ for default connection information. You can edit these files to provide different credentials on your machine if you must, but obviously you should not push any such changes back to Rails.
-You can now run tests as you did for +sqlite3+, the tasks are
+You can now run the tests as you did for +sqlite3+. The tasks are respectively
<shell>
test_mysql
@@ -192,7 +193,7 @@ test_mysql2
test_postgresql
</shell>
-respectively. As we mentioned before
+As we mentioned before
<shell>
$ bundle exec rake test
@@ -200,9 +201,9 @@ $ bundle exec rake test
will now run the four of them in turn.
-You can also invoke +test_jdbcmysql+, +test_jdbcsqlite3+ or +test_jdbcpostgresql+. Check out the file +activerecord/RUNNING_UNIT_TESTS+ for information on running more targeted database tests, or the file +ci/travis.rb+ to see the test suite that the continuous integration server runs.
+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
+h4. Older Versions of Ruby on Rails
If you want to add a fix to older versions of Ruby on Rails, you'll need to set up and switch to your own local tracking branch. Here is an example to switch to the 3-0-stable branch:
@@ -219,9 +220,9 @@ As a next step beyond reporting issues, you can help the core team resolve exist
h4. Verifying Bug Reports
-For starters, it helps to just verify bug reports. Can you reproduce the reported issue on your own computer? If so, you can add a comment to the issue saying that you're seeing the same thing.
+For starters, it helps just to verify bug reports. Can you reproduce the reported issue on your own computer? If so, you can add a comment to the issue saying that you're seeing the same thing.
-If something is very vague, can you help squish it down into something specific? Maybe you can provide additional information to help reproduce a bug, or eliminate needless steps that aren't required to help demonstrate the problem.
+If something is very vague, can you help squash it down into something specific? Maybe you can provide additional information to help reproduce a bug, or help by eliminating needless steps that aren't required to demonstrate the problem.
If you find a bug report without a test, it's very useful to contribute a failing test. This is also a great way to get started exploring the source code: looking at the existing test files will teach you how to write more tests. New tests are best contributed in the form of a patch, as explained later on in the "Contributing to the Rails Code" section.
@@ -229,51 +230,51 @@ Anything you can do to make bug reports more succinct or easier to reproduce is
h4. Testing Patches
-You can also help out by examining pull requests that have been submitted to Ruby on Rails via GitHub. To apply someone's changes you need to first create a dedicated branch:
+You can also help out by examining pull requests that have been submitted to Ruby on Rails via GitHub. To apply someone's changes you need first to create a dedicated branch:
<shell>
$ git checkout -b testing_branch
</shell>
-Then you can use their remote branch to update your codebase. For example, let's say the GitHub user JohnSmith has forked and pushed to the topic branch located at https://github.com/JohnSmith/rails.
+Then you can use their remote branch to update your codebase. For example, let's say the GitHub user JohnSmith has forked and pushed to a topic branch "orange" located at https://github.com/JohnSmith/rails.
<shell>
$ git remote add JohnSmith git://github.com/JohnSmith/rails.git
-$ git pull JohnSmith topic
+$ git pull JohnSmith orange
</shell>
After applying their branch, test it out! Here are some things to think about:
* Does the change actually work?
* Are you happy with the tests? Can you follow what they're testing? Are there any tests missing?
-* Does it have proper documentation coverage? Should documentation elsewhere be updated?
+* Does it have the proper documentation coverage? Should documentation elsewhere be updated?
* Do you like the implementation? Can you think of a nicer or faster way to implement a part of their change?
Once you're happy that the pull request contains a good change, comment on the GitHub issue indicating your approval. Your comment should indicate that you like the change and what you like about it. Something like:
<blockquote>
-I like the way you've restructured that code in generate_finder_sql, much nicer. The tests look good too.
+I like the way you've restructured that code in generate_finder_sql -- much nicer. The tests look good too.
</blockquote>
If your comment simply says "+1", then odds are that other reviewers aren't going to take it too seriously. Show that you took the time to review the pull request.
h3. Contributing to the Rails Documentation
-Ruby on Rails has two main sets of documentation: The guides help you to learn Ruby on Rails, and the API is a reference.
+Ruby on Rails has two main sets of documentation: the guides help you in learning about Ruby on Rails, and the API is a reference.
-You can help improve the Rails guides by making them more coherent, adding missing information, correcting factual errors, fixing typos, bringing it up to date with the latest edge Rails. To get involved in the translation of Rails guides, please see "Translating Rails Guides":https://wiki.github.com/lifo/docrails/translating-rails-guides.
+You can help improve the Rails guides by making them more coherent, consistent or readable, adding missing information, correcting factual errors, fixing typos, or bringing it up to date with the latest edge Rails. To get involved in the translation of Rails guides, please see "Translating Rails Guides":https://wiki.github.com/lifo/docrails/translating-rails-guides.
-If you're confident about your changes, you can push them yourself directly via "docrails":https://github.com/lifo/docrails. docrails is a branch with an *open commit policy* and public write access. Commits to docrails are still reviewed, but that happens after they are pushed. docrails is merged with master regularly, so you are effectively editing the Ruby on Rails documentation.
+If you're confident about your changes, you can push them directly yourself via "docrails":https://github.com/lifo/docrails. Docrails is a branch with an *open commit policy* and public write access. Commits to docrails are still reviewed, but this happens after they are pushed. Docrails is merged with master regularly, so you are effectively editing the Ruby on Rails documentation.
If you are unsure of the documentation changes, you can create an issue in the "Rails":https://github.com/rails/rails/issues issues tracker on GitHub.
When working with documentation, please take into account the "API Documentation Guidelines":api_documentation_guidelines.html and the "Ruby on Rails Guides Guidelines":ruby_on_rails_guides_guidelines.html.
-NOTE: As explained earlier, ordinary code patches should have proper documentation coverage. docrails is only used for isolated documentation improvements.
+NOTE: As explained earlier, ordinary code patches should have proper documentation coverage. Docrails is only used for isolated documentation improvements.
-NOTE: To help our CI servers you can add [ci skip] tag to your documentation commit message to skip build on that commit. Please remember to use it for commits containing only documentation changes.
+NOTE: To help our CI servers you can add [ci skip] to your documentation commit message to skip build on that commit. Please remember to use it for commits containing only documentation changes.
-WARNING: docrails has a very strict policy: no code can be touched whatsoever, no matter how trivial or small the change. Only RDoc and guides can be edited via docrails. Also, CHANGELOGs should never be edited in docrails.
+WARNING: Docrails has a very strict policy: no code can be touched whatsoever, no matter how trivial or small the change. Only RDoc and guides can be edited via docrails. Also, CHANGELOGs should never be edited in docrails.
h3. Contributing to the Rails Code
@@ -292,37 +293,37 @@ $ cd rails
$ git checkout -b my_new_branch
</shell>
-It doesn’t really matter what name you use, because this branch will only exist on your local computer and your personal repository on Github. It won't be part of the Rails git repository.
+It doesn’t matter much what name you use, because this branch will only exist on your local computer and your personal repository on Github. It won't be part of the Rails git repository.
h4. Write Your Code
Now get busy and add or edit code. You’re on your branch now, so you can write whatever you want (you can check to make sure you’re on the right branch with +git branch -a+). But if you’re planning to submit your change back for inclusion in Rails, keep a few things in mind:
-* Get the code right
-* Use Rails idioms and helpers
-* Include tests that fail without your code, and pass with it
-* Update the documentation, the surrounding one, examples elsewhere, guides, whatever is affected by your contribution
+* Get the code right.
+* Use Rails idioms and helpers.
+* Include tests that fail without your code, and pass with it.
+* Update the (surrounding) documentation, examples elsewhere, and the guides: whatever is affected by your contribution.
h4. Follow the Coding Conventions
Rails follows a simple set of coding style conventions.
-* Two spaces, no tabs.
-* No trailing whitespace. Blank lines should not have any space.
+* Two spaces, no tabs (for indentation).
+* No trailing whitespace. Blank lines should not have any spaces.
* Indent after private/protected.
* Prefer +&amp;&amp;+/+||+ over +and+/+or+.
-* Prefer class << self block over self.method for class methods.
-* +MyClass.my_method(my_arg)+ not +my_method( my_arg )+ or +my_method my_arg+.
-* a = b and not a=b.
-* Follow the conventions you see used in the source already.
+* Prefer class << self over self.method for class methods.
+* Use +MyClass.my_method(my_arg)+ not +my_method( my_arg )+ or +my_method my_arg+.
+* Use a = b and not a=b.
+* Follow the conventions in the source you see used already.
-These are some guidelines and please use your best judgment in using them.
+The above are guidelines -- please use your best judgment in using them.
h4. Sanity Check
You should not be the only person who looks at the code before you submit it. You know at least one other Rails developer, right? Show them what you’re doing and ask for feedback. Doing this in private before you push a patch out publicly is the “smoke test” for a patch: if you can’t convince one other developer of the beauty of your code, you’re unlikely to convince the core team either.
-You might also want to check out the "RailsBridge BugMash":http://wiki.railsbridge.org/projects/railsbridge/wiki/BugMash as a way to get involved in a group effort to improve Rails. This can help you get started and help check your code when you're writing your first patches.
+You might want also to check out the "RailsBridge BugMash":http://wiki.railsbridge.org/projects/railsbridge/wiki/BugMash as a way to get involved in a group effort to improve Rails. This can help you get started and help you check your code when you're writing your first patches.
h4. Commit Your Changes
@@ -332,9 +333,9 @@ When you're happy with the code on your computer, you need to commit the changes
$ git commit -a -m "Here is a commit message on what I changed in this commit"
</shell>
-TIP. Please squash your commits into a single commit when appropriate. This simplifies future cherry picks, and also keeps the git log clean.
+TIP. Please squash your commits into a single commit when appropriate. This simplifies future cherry picks, and also keeps the git log clean.
-h4. Update master
+h4. Update Master
It’s pretty likely that other changes to master have happened while you were working. Go get them:
@@ -372,13 +373,13 @@ h4. Issue a Pull Request
Navigate to the Rails repository you just pushed to (e.g. https://github.com/your-user-name/rails) and press "Pull Request" in the upper right hand corner.
-Write your branch name in branch field (is filled with master by default) and press "Update Commit Range"
+Write your branch name in the branch field (this is filled with "master" by default) and press "Update Commit Range".
-Ensure the changesets you introduced are included in the "Commits" tab and that the "Files Changed" incorporate all of your changes.
+Ensure the changesets you introduced are included in the "Commits" tab. Ensure that the "Files Changed" incorporate all of your changes.
-Fill in some details about your potential patch including a meaningful title. When finished, press "Send pull request." Rails Core will be notified about your submission.
+Fill in some details about your potential patch including a meaningful title. When finished, press "Send pull request". The Rails core team will be notified about your submission.
-h4. Get Some Feedback
+h4. Get some Feedback
Now you need to get other people to look at your patch, just as you've looked at other people's patches. You can use the "rubyonrails-core mailing list":http://groups.google.com/group/rubyonrails-core/ or the #rails-contrib channel on IRC freenode for this. You might also try just talking to Rails developers that you know.
diff --git a/guides/source/debugging_rails_applications.textile b/guides/source/debugging_rails_applications.textile
index 57c7786636..903ed59e7b 100644
--- a/guides/source/debugging_rails_applications.textile
+++ b/guides/source/debugging_rails_applications.textile
@@ -191,7 +191,7 @@ Completed in 0.01224 (81 reqs/sec) | DB: 0.00044 (3%) | 302 Found [http://localh
Adding extra logging like this makes it easy to search for unexpected or unusual behavior in your logs. If you add extra logging, be sure to make sensible use of log levels, to avoid filling your production logs with useless trivia.
-h3. Debugging with +ruby-debug+
+h3. Debugging with the +debugger+ gem
When your code is behaving in unexpected ways, you can try printing to logs or the console to diagnose the problem. Unfortunately, there are times when this sort of error tracking is not effective in finding the root cause of a problem. When you actually need to journey into your running source code, the debugger is your best companion.
@@ -199,17 +199,13 @@ The debugger can also help you if you want to learn about the Rails source code
h4. Setup
-The debugger used by Rails, +ruby-debug+, comes as a gem. To install it, just run:
+Rails uses the +debugger+ gem to set breakpoints and step through live code. To install it, just run:
<shell>
-$ sudo gem install ruby-debug
+$ gem install debugger
</shell>
-TIP: If you are using Ruby 1.9, you can install a compatible version of +ruby-debug+ by running +sudo gem install ruby-debug19+
-
-In case you want to download a particular version or get the source code, refer to the "project's page on rubyforge":http://rubyforge.org/projects/ruby-debug/.
-
-Rails has had built-in support for ruby-debug since Rails 2.0. Inside any Rails application you can invoke the debugger by calling the +debugger+ method.
+Rails has had built-in support for debugging since Rails 2.0. Inside any Rails application you can invoke the debugger by calling the +debugger+ method.
Here's an example:
@@ -238,11 +234,11 @@ $ rails server --debugger
...
</shell>
-TIP: In development mode, you can dynamically +require \'ruby-debug\'+ instead of restarting the server, if it was started without +--debugger+.
+TIP: In development mode, you can dynamically +require \'debugger\'+ instead of restarting the server, if it was started without +--debugger+.
h4. The Shell
-As soon as your application calls the +debugger+ method, the debugger will be started in a debugger shell inside the terminal window where you launched your application server, and you will be placed at ruby-debug's prompt +(rdb:n)+. The _n_ is the thread number. The prompt will also show you the next line of code that is waiting to run.
+As soon as your application calls the +debugger+ method, the debugger will be started in a debugger shell inside the terminal window where you launched your application server, and you will be placed at the debugger's prompt +(rdb:n)+. The _n_ is the thread number. The prompt will also show you the next line of code that is waiting to run.
If you got there by a browser request, the browser tab containing the request will be hung until the debugger has finished and the trace has finished processing the entire request.
@@ -270,7 +266,7 @@ continue edit frame method putl set tmate where
TIP: To view the help menu for any command use +help &lt;command-name&gt;+ in active debug mode. For example: _+help var+_
-The next command to learn is one of the most useful: +list+. You can also abbreviate ruby-debug commands by supplying just enough letters to distinguish them from other commands, so you can also use +l+ for the +list+ command.
+The next command to learn is one of the most useful: +list+. You can abbreviate any debugging command by supplying just enough letters to distinguish them from other commands, so you can also use +l+ for the +list+ command.
This command shows you where you are in the code by printing 10 lines centered around the current line; the current line in this particular case is line 6 and is marked by +=>+.
@@ -347,7 +343,7 @@ h4. The Context
When you start debugging your application, you will be placed in different contexts as you go through the different parts of the stack.
-ruby-debug creates a context when a stopping point or an event is reached. The context has information about the suspended program which enables a debugger to inspect the frame stack, evaluate variables from the perspective of the debugged program, and contains information about the place where the debugged program is stopped.
+The debugger creates a context when a stopping point or an event is reached. The context has information about the suspended program which enables a debugger to inspect the frame stack, evaluate variables from the perspective of the debugged program, and contains information about the place where the debugged program is stopped.
At any time you can call the +backtrace+ command (or its alias +where+) to print the backtrace of the application. This can be very helpful to know how you got where you are. If you ever wondered about how you got somewhere in your code, then +backtrace+ will supply the answer.
@@ -463,7 +459,7 @@ h4. Step by Step
Now you should know where you are in the running trace and be able to print the available variables. But lets continue and move on with the application execution.
-Use +step+ (abbreviated +s+) to continue running your program until the next logical stopping point and return control to ruby-debug.
+Use +step+ (abbreviated +s+) to continue running your program until the next logical stopping point and return control to the debugger.
TIP: You can also use <tt>step<plus> n</tt> and <tt>step- n</tt> to move forward or backward +n+ steps respectively.
@@ -485,12 +481,12 @@ class Author < ActiveRecord::Base
end
</ruby>
-TIP: You can use ruby-debug while using +rails console+. Just remember to +require "ruby-debug"+ before calling the +debugger+ method.
+TIP: You can use the debugger while using +rails console+. Just remember to +require "debugger"+ before calling the +debugger+ method.
<shell>
$ rails console
Loading development environment (Rails 3.1.0)
->> require "ruby-debug"
+>> require "debugger"
=> []
>> author = Author.first
=> #<Author id: 1, first_name: "Bob", last_name: "Smith", created_at: "2008-07-31 12:46:10", updated_at: "2008-07-31 12:46:10">
@@ -603,7 +599,7 @@ A simple quit tries to terminate all threads in effect. Therefore your server wi
h4. Settings
-There are some settings that can be configured in ruby-debug to make it easier to debug your code. Here are a few of the available options:
+The +debugger+ gem can automatically show the code you're stepping through and reload it when you change it in an editor. Here are a few of the available options:
* +set reload+: Reload source code when changed.
* +set autolist+: Execute +list+ command on every breakpoint.
@@ -612,7 +608,7 @@ There are some settings that can be configured in ruby-debug to make it easier t
You can see the full list by using +help set+. Use +help set _subcommand_+ to learn about a particular +set+ command.
-TIP: You can include any number of these configuration lines inside a +.rdebugrc+ file in your HOME directory. ruby-debug will read this file every time it is loaded and configure itself accordingly.
+TIP: You can save these settings in an +.rdebugrc+ file in your home directory. The debugger reads these global settings when it starts.
Here's a good start for an +.rdebugrc+:
@@ -637,7 +633,7 @@ If a Ruby object does not go out of scope, the Ruby Garbage Collector won't swee
To install it run:
<shell>
-$ sudo gem install bleak_house
+$ gem install bleak_house
</shell>
Then setup your application for profiling. Then add the following at the bottom of config/environment.rb:
@@ -703,11 +699,12 @@ There are some Rails plugins to help you to find errors and debug your applicati
h3. References
* "ruby-debug Homepage":http://www.datanoise.com/ruby-debug
+* "debugger Homepage":http://github.com/cldwalker/debugger
* "Article: Debugging a Rails application with ruby-debug":http://www.sitepoint.com/article/debug-rails-app-ruby-debug/
* "ruby-debug Basics screencast":http://brian.maybeyoureinsane.net/blog/2007/05/07/ruby-debug-basics-screencast/
-* "Ryan Bate's ruby-debug screencast":http://railscasts.com/episodes/54-debugging-with-ruby-debug
-* "Ryan Bate's stack trace screencast":http://railscasts.com/episodes/24-the-stack-trace
-* "Ryan Bate's logger screencast":http://railscasts.com/episodes/56-the-logger
+* "Ryan Bates' debugging ruby (revised) screencast":http://railscasts.com/episodes/54-debugging-ruby-revised
+* "Ryan Bates' stack trace screencast":http://railscasts.com/episodes/24-the-stack-trace
+* "Ryan Bates' logger screencast":http://railscasts.com/episodes/56-the-logger
* "Debugging with ruby-debug":http://bashdb.sourceforge.net/ruby-debug.html
* "ruby-debug cheat sheet":http://cheat.errtheblog.com/s/rdebug/
* "Ruby on Rails Wiki: How to Configure Logging":http://wiki.rubyonrails.org/rails/pages/HowtoConfigureLogging
diff --git a/guides/source/engines.textile b/guides/source/engines.textile
index 6ae9504c23..71bcf6b713 100644
--- a/guides/source/engines.textile
+++ b/guides/source/engines.textile
@@ -16,7 +16,7 @@ Engines can be considered miniature applications that provide functionality to t
Therefore, engines and applications can be thought of almost the same thing, just with very minor differences, as you'll see throughout this guide. Engines and applications also share a common structure.
-Engines are also closely related to plugins where the two share a common +lib+ directory structure and are both generated using the +rails plugin new+ generator. The difference being that an engine is considered a "full plugin" by Rails -- as indicated by the +--full+ option that's passed to the generator command -- but this guide will refer to them simply as "engines" throughout. An engine *can* be a plugin, and a plugin *can* be an engine.
+Engines are also closely related to plugins where the two share a common +lib+ directory structure and are both generated using the +rails plugin new+ generator. The difference being that an engine is considered a "full plugin" by Rails as indicated by the +--full+ option that's passed to the generator command, but this guide will refer to them simply as "engines" throughout. An engine *can* be a plugin, and a plugin *can* be an engine.
The engine that will be created in this guide will be called "blorgh". The engine will provide blogging functionality to its host applications, allowing for new posts and comments to be created. At the beginning of this guide, you will be working solely within the engine itself, but in later sections you'll see how to hook it into an application.
@@ -51,7 +51,7 @@ h5. Critical files
At the root of this brand new engine's directory, lives a +blorgh.gemspec+ file. When you include the engine into the application later on, you will do so with this line in a Rails application's +Gemfile+:
<ruby>
- gem 'blorgh', :path => "vendor/engines/blorgh"
+gem 'blorgh', :path => "vendor/engines/blorgh"
</ruby>
By specifying it as a gem within the +Gemfile+, Bundler will load it as such, parsing this +blorgh.gemspec+ file and requiring a file within the +lib+ directory called +lib/blorgh.rb+. This file requires the +blorgh/engine.rb+ file (located at +lib/blorgh/engine.rb+) and defines a base module called +Blorgh+.
@@ -77,7 +77,7 @@ end
By inheriting from the +Rails::Engine+ class, this gem notifies Rails that there's an engine at the specified path, and will correctly mount the engine inside the application, performing tasks such as adding the +app+ directory of the engine to the load path for models, mailers, controllers and views.
-The +isolate_namespace+ method here deserves special notice. This call is responsible for isolating the controllers, models, routes and other things into their own namespace, away from similar components inside hte application. Without this, there is a possibility that the engine's components could "leak" into the application, causing unwanted disruption, or that important engine components could be overriden by similarly named things within the application. One of the examples of such conflicts are helpers. Without calling +isolate_namespace+, engine's helpers would be included in application's controllers.
+The +isolate_namespace+ method here deserves special notice. This call is responsible for isolating the controllers, models, routes and other things into their own namespace, away from similar components inside the application. Without this, there is a possibility that the engine's components could "leak" into the application, causing unwanted disruption, or that important engine components could be overridden by similarly named things within the application. One of the examples of such conflicts are helpers. Without calling +isolate_namespace+, engine's helpers would be included in application's controllers.
NOTE: It is *highly* recommended that the +isolate_namespace+ line be left within the +Engine+ class definition. Without it, classes generated in an engine *may* conflict with an application.
@@ -115,7 +115,6 @@ The +test+ directory is where tests for the engine will go. To test the engine,
<ruby>
Rails.application.routes.draw do
-
mount Blorgh::Engine => "/blorgh"
end
</ruby>
@@ -126,7 +125,7 @@ Also in the test directory is the +test/integration+ directory, where integratio
h3. Providing engine functionality
-The engine that this guide covers will provide posting and commenting functionality and follows a similar thread to the "Getting Started Guide":getting-started.html, with some new twists.
+The engine that this guide covers will provide posting and commenting functionality and follows a similar thread to the "Getting Started Guide":getting_started.html, with some new twists.
h4. Generating a post resource
@@ -179,7 +178,6 @@ After that, a line for the resource is inserted into the +config/routes.rb+ file
<ruby>
Blorgh::Engine.routes.draw do
resources :posts
-
end
</ruby>
@@ -219,17 +217,13 @@ By default, the scaffold styling is not applied to the engine as the engine's la
<%= stylesheet_link_tag "scaffold" %>
</erb>
-You can see what the engine has so far by running +rake db:migrate+ at the root of our engine to run the migration generated by the scaffold generator, and then running +rails server+. When you open +http://localhost:3000/blorgh/posts+ you will see the default scaffold that has been generated.
-
-!images/engines_scaffold.png(Blank engine scaffold)!
-
-Click around! You've just generated your first engine's first functions.
+You can see what the engine has so far by running +rake db:migrate+ at the root of our engine to run the migration generated by the scaffold generator, and then running +rails server+ in +test/dummy+. When you open +http://localhost:3000/blorgh/posts+ you will see the default scaffold that has been generated. Click around! You've just generated your first engine's first functions.
If you'd rather play around in the console, +rails console+ will also work just like a Rails application. Remember: the +Post+ model is namespaced, so to reference it you must call it as +Blorgh::Post+.
<ruby>
- >> Blorgh::Post.find(1)
- => #<Blorgh::Post id: 1 ...>
+>> Blorgh::Post.find(1)
+=> #<Blorgh::Post id: 1 ...>
</ruby>
One final thing is that the +posts+ resource for this engine should be the root of the engine. Whenever someone goes to the root path where the engine is mounted, they should be shown a list of posts. This can be made to happen if this line is inserted into the +config/routes.rb+ file inside the engine:
@@ -263,7 +257,7 @@ create test/fixtures/blorgh/comments.yml
This generator call will generate just the necessary model files it needs, namespacing the files under a +blorgh+ directory and creating a model class called +Blorgh::Comment+.
-To show the comments on a post, edit +app/views/posts/show.html.erb+ and add this line before the "Edit" link:
+To show the comments on a post, edit +app/views/blorgh/posts/show.html.erb+ and add this line before the "Edit" link:
<erb>
<h3>Comments</h3>
@@ -355,11 +349,11 @@ end
This is the final part required to get the new comment form working. Displaying the comments however, is not quite right yet. If you were to create a comment right now you would see this error:
-<text>
- Missing partial blorgh/comments/comment with {:handlers=>[:erb, :builder], :formats=>[:html], :locale=>[:en, :en]}. Searched in:
- * "/Users/ryan/Sites/side_projects/blorgh/test/dummy/app/views"
- * "/Users/ryan/Sites/side_projects/blorgh/app/views"
-</text>
+<plain>
+Missing partial blorgh/comments/comment with {:handlers=>[:erb, :builder], :formats=>[:html], :locale=>[:en, :en]}. Searched in:
+ * "/Users/ryan/Sites/side_projects/blorgh/test/dummy/app/views"
+ * "/Users/ryan/Sites/side_projects/blorgh/app/views"
+</plain>
The engine is unable to find the partial required for rendering the comments. Rails has looked firstly in the application's (+test/dummy+) +app/views+ directory and then in the engine's +app/views+ directory. When it can't find it, it will throw this error. The engine knows to look for +blorgh/comments/comment+ because the model object it is receiving is from the +Blorgh::Comment+ class.
@@ -511,11 +505,11 @@ $ rake blorgh:install:migrations
Notice here that only _one_ migration was copied over here. This is because the first two migrations were copied over the first time this command was run.
-<shell>
- NOTE: Migration [timestamp]_create_blorgh_posts.rb from blorgh has been skipped. Migration with the same name already exists.
- NOTE: Migration [timestamp]_create_blorgh_comments.rb from blorgh has been skipped. Migration with the same name already exists.
- Copied migration [timestamp]_add_author_id_to_blorgh_posts.rb from blorgh
-</shell>
+<plain>
+NOTE Migration [timestamp]_create_blorgh_posts.rb from blorgh has been skipped. Migration with the same name already exists.
+NOTE Migration [timestamp]_create_blorgh_comments.rb from blorgh has been skipped. Migration with the same name already exists.
+Copied migration [timestamp]_add_author_id_to_blorgh_posts.rb from blorgh
+</plain>
Run this migration using this command:
@@ -536,9 +530,9 @@ Finally, the author's name should be displayed on the post's page. Add this code
By outputting +@post.author+ using the +<%=+ tag the +to_s+ method will be called on the object. By default, this will look quite ugly:
-<text>
+<plain>
#<User:0x00000100ccb3b0>
-</text>
+</plain>
This is undesirable and it would be much better to have the user's name there. To do this, add a +to_s+ method to the +User+ class within the application:
@@ -581,9 +575,9 @@ self.author = Blorgh.user_class.constantize.find_or_create_by_name(author_name)
To save having to call +constantize+ on the +user_class+ result all the time, you could instead just override the +user_class+ getter method inside the +Blorgh+ module in the +lib/blorgh.rb+ file to always call +constantize+ on the saved value before returning the result:
<ruby>
- def self.user_class
- @@user_class.constantize
- end
+def self.user_class
+ @@user_class.constantize
+end
</ruby>
This would then turn the above code for +self.author=+ into this:
@@ -663,10 +657,6 @@ Try this now by creating a new file at +app/views/blorgh/posts/index.html.erb+ a
<% end %>
</erb>
-Rather than looking like the default scaffold, the page will now look like this:
-
-!images/engines_post_override.png(Engine scaffold overriden)!
-
h4. Routes
Routes inside an engine are, by default, isolated from the application. This is done by the +isolate_namespace+ call inside the +Engine+ class. This essentially means that the application and its engines can have identically named routes, and that they will not clash.
@@ -674,9 +664,9 @@ Routes inside an engine are, by default, isolated from the application. This is
Routes inside an engine are drawn on the +Engine+ class within +config/routes.rb+, like this:
<ruby>
- Blorgh::Engine.routes.draw do
- resources :posts
- end
+Blorgh::Engine.routes.draw do
+ resources :posts
+end
</ruby>
By having isolated routes such as this, if you wish to link to an area of an engine from within an application, you will need to use the engine's routing proxy method. Calls to normal routing methods such as +posts_path+ may end up going to undesired locations if both the application and the engine both have such a helper defined.
@@ -705,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.
@@ -717,11 +707,26 @@ Imagine that you did have an asset located at +app/assets/stylesheets/blorgh/sty
You can also specify these assets as dependencies of other assets using the Asset Pipeline require statements in processed files:
-<css>
+<plain>
/*
*= require blorgh/style
*/
-</css>
+</plain>
+
+h4. Separate Assets & Precompiling
+
+There are some situations where your engine's assets not required by the host application. For example, say that you've created
+an admin functionality that only exists for your engine. In this case, the host application doesn't need to require +admin.css+
+or +admin.js+. Only the gem's admin layout needs these assets. It doesn't make sense for the host app to include +"blorg/admin.css"+ in it's stylesheets. In this situation, you should explicitly define these assets for precompilation.
+This tells sprockets to add you engine assets when +rake assets:precompile+ is ran.
+
+You can define assets for precompilation in +engine.rb+
+
+<ruby>
+initializer do |app|
+ app.config.assets.precompile += %w(admin.css admin.js)
+end
+</ruby>
For more information, read the "Asset Pipeline guide":http://guides.rubyonrails.org/asset_pipeline.html
diff --git a/guides/source/form_helpers.textile b/guides/source/form_helpers.textile
index 8934667c5e..b6420db798 100644
--- a/guides/source/form_helpers.textile
+++ b/guides/source/form_helpers.textile
@@ -89,7 +89,7 @@ form_tag(:controller => "people", :action => "search", :method => "get", :class
# => '<form accept-charset="UTF-8" action="/people/search?method=get&class=nifty_form" method="post">'
</ruby>
-Here, +method+ and +class+ are appended to the query string of the generated URL because you even though you mean to write two hashes, you really only specified one. So you need to tell Ruby which is which by delimiting the first hash (or both) with curly brackets. This will generate the HTML you expect:
+Here, +method+ and +class+ are appended to the query string of the generated URL because even though you mean to write two hashes, you really only specified one. So you need to tell Ruby which is which by delimiting the first hash (or both) with curly brackets. This will generate the HTML you expect:
<ruby>
form_tag({:controller => "people", :action => "search"}, :method => "get", :class => "nifty_form")
diff --git a/guides/source/generators.textile b/guides/source/generators.textile
index 920ff997ae..2e9ab0526d 100644
--- a/guides/source/generators.textile
+++ b/guides/source/generators.textile
@@ -451,6 +451,27 @@ Adds a specified source to +Gemfile+:
add_source "http://gems.github.com"
</ruby>
+h4. +inject_into_file+
+
+Injects a block of code into a defined position in your file.
+
+<ruby>
+inject_into_file 'name_of_file.rb', :after => "#The code goes below this line. Don't forget the Line break at the end\n" do <<-'RUBY'
+ puts "Hello World"
+RUBY
+end
+</ruby>
+
+h4. +gsub_file+
+
+Replaces text inside a file.
+
+<ruby>
+gsub_file 'name_of_file.rb', 'method.to_be_replaced', 'method.the_replacing_code'
+</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.
+
h4. +application+
Adds a line to +config/application.rb+ directly after the application class definition.
diff --git a/guides/source/getting_started.textile b/guides/source/getting_started.textile
index fdae21caf2..b48ebbceb2 100644
--- a/guides/source/getting_started.textile
+++ b/guides/source/getting_started.textile
@@ -10,7 +10,7 @@ you should be familiar with:
endprologue.
-WARNING. This Guide is based on Rails 3.1. Some of the code shown here will not
+WARNING. This Guide is based on Rails 3.2. Some of the code shown here will not
work in earlier versions of Rails.
WARNING: The Edge version of this guide is currently being re-worked. Please excuse us while we re-arrange the place.
@@ -27,8 +27,8 @@ prerequisites installed:
TIP: Note that Ruby 1.8.7 p248 and p249 have marshaling bugs that crash Rails
3.0. Ruby Enterprise Edition have these fixed since release 1.8.7-2010.02
though. On the 1.9 front, Ruby 1.9.1 is not usable because it outright segfaults
-on Rails 3.0, so if you want to use Rails 3 with 1.9.x jump on 1.9.2 for smooth
-sailing.
+on Rails 3.0, so if you want to use Rails 3 with 1.9.x jump on 1.9.2 or
+1.9.3 for smooth sailing.
* The "RubyGems":http://rubyforge.org/frs/?group_id=126 packaging system
** If you want to learn more about RubyGems, please read the "RubyGems User Guide":http://docs.rubygems.org/read/book/1
@@ -45,10 +45,6 @@ internet for learning Ruby, including:
h3. What is Rails?
-TIP: This section goes into the background and philosophy of the Rails framework
-in detail. You can safely skip this section and come back to it at a later time.
-Section 3 starts you on the path to creating your first Rails application.
-
Rails is a web application development framework written in the Ruby language.
It is designed to make programming web applications easier by making assumptions
about what every developer needs to get started. It allows you to write less
@@ -73,7 +69,8 @@ h3. Creating a New Rails Project
The best way to use this guide is to follow each step as it happens, no code or
step needed to make this example application has been left out, so you can
-literally follow along step by step. You can get the complete code "here":https://github.com/lifo/docrails/tree/master/railties/guides/code/getting_started.
+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
(very) simple weblog. Before you can start building the application, you need to
@@ -97,7 +94,7 @@ To verify that you have everything installed correctly, you should be able to ru
$ rails --version
</shell>
-If it says something like "Rails 3.2.2" you are ready to continue.
+If it says something like "Rails 3.2.3" you are ready to continue.
h4. Creating the Blog Application
@@ -111,7 +108,7 @@ $ rails new blog
This will create a Rails application called Blog in a directory called blog.
-TIP: You can see all of the switches 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 <tt>rails new -h</tt>.
After you create the blog application, switch to its folder to continue work directly in that application:
@@ -119,10 +116,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 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 <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:
|_.File/Folder|_.Purpose|
-|app/|Contains the controllers, models, views and assets for your application. You'll focus on this folder for the remainder of this guide.|
+|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.|
|config/|Configure your application's runtime rules, routes, database, and more. This is covered in more detail in "Configuring Rails Applications":configuring.html|
|config.ru|Rack configuration for Rack based servers used to start the application.|
|db/|Contains your current database schema, as well as the database migrations.|
@@ -140,7 +137,7 @@ The +rails new blog+ command we ran above created a folder in your working direc
h3. Hello, Rails!
-One of the traditional places to start with a new language is by getting some text up on screen quickly. To do this, you need to get your Rails application server running.
+To begin with, let's get some text up on screen quickly. To do this, you need to get your Rails application server running.
h4. Starting up the Web Server
@@ -152,11 +149,11 @@ $ rails server
TIP: Compiling CoffeeScript to JavaScript requires a JavaScript runtime and the absence of a runtime will give you an +execjs+ error. Usually Mac OS X and Windows come with a JavaScript runtime installed. Rails adds the +therubyracer+ gem to Gemfile in a commented line for new apps and you can uncomment if you need it. +therubyrhino+ is the recommended runtime for JRuby users and is added by default to Gemfile in apps generated under JRuby. You can investigate about all the supported runtimes at "ExecJS":https://github.com/sstephenson/execjs#readme.
-This will fire up an instance of a webserver built into Ruby called WEBrick by default. To see your application in action, open a browser window and navigate to "http://localhost:3000":http://localhost:3000. You should see Rails' default information page:
+This will fire up WEBrick, a webserver built into Ruby by default. To see your application in action, open a browser window and navigate to "http://localhost:3000":http://localhost:3000. You should see the Rails default information page:
!images/rails_welcome.png(Welcome Aboard screenshot)!
-TIP: To stop the web server, hit Ctrl+C in the terminal window where it's running. In development mode, Rails does not generally require you to stop the server; changes you make in files will be automatically picked up by the server.
+TIP: To stop the web server, hit Ctrl+C in the terminal window where it's running. In development mode, Rails does not generally require you to restart the server; changes you make in files will be automatically picked up by the server.
The "Welcome Aboard" page is the _smoke test_ for a new Rails application: it makes sure that you have your software configured correctly enough to serve a page. You can also click on the _About your application’s environment_ link to see a summary of your application's environment.
@@ -164,7 +161,7 @@ h4. Say "Hello", Rails
To get Rails saying "Hello", you need to create at minimum a _controller_ and a _view_.
-A controller's purpose is to receive specific requests for the application. What controller receives what request is determined by the _routing_. There is very often more than one route to each controller, and different routes can be served by different _actions_. Each action's purpose is to collect information to provide it to a view.
+A controller's purpose is to receive specific requests for the application. _Routing_ decides which controller receives which requests. Often, there is more than one route to each controller, and different routes can be served by different _actions_. Each action's purpose is to collect information to provide it to a view.
A view's purpose is to display this information in a human readable format. An important distinction to make is that it is the _controller_, not the view, where information is collected. The view should just display that information. By default, view templates are written in a language called ERB (Embedded Ruby) which is converted by the request cycle in Rails before being sent to the user.
@@ -225,7 +222,6 @@ h4. Laying down the ground work
The first thing that you are going to need to create a new post within the application is a place to do that. A great place for that would be at +/posts/new+. If you attempt to navigate to that now -- by visiting "http://localhost:3000/posts/new":http://localhost:3000/posts/new -- Rails will give you a routing error:
-
!images/getting_started/routing_error_no_route_matches.png(A routing error, no route matches /posts/new)!
This is because there is nowhere inside the routes for the application -- defined inside +config/routes.rb+ -- that defines this route. By default, Rails has no routes configured at all, and so you must define your routes as you need them.
@@ -240,7 +236,7 @@ This route is a super-simple route: it defines a new route that only responds to
With the route defined, requests can now be made to +/posts/new+ in the application. Navigate to "http://localhost:3000/posts/new":http://localhost:3000/posts/new and you'll see another routing error:
-!images/getting_started/routing_error_no_controller.png(Another routing error, uninitialized constant PostsController)
+!images/getting_started/routing_error_no_controller.png(Another routing error, uninitialized constant PostsController)!
This error is happening because this route need a controller to be defined. The route is attempting to find that controller so it can serve the request, but with the controller undefined, it just can't do that. The solution to this particular problem is simple: you need to create a controller called +PostsController+. You can do this by running this command:
@@ -259,7 +255,7 @@ A controller is simply a class that is defined to inherit from +ApplicationContr
If you refresh "http://localhost:3000/posts/new":http://localhost:3000/posts/new now, you'll get a new error:
-!images/getting_started/unknown_action_new_for_posts.png(Unknown action new for PostsController!)
+!images/getting_started/unknown_action_new_for_posts.png(Unknown action new for PostsController!)!
This error indicates that Rails cannot find the +new+ action inside the +PostsController+ that you just generated. This is because when controllers are generated in Rails they are empty by default, unless you tell it you wanted actions during the generation process.
@@ -272,7 +268,7 @@ end
With the +new+ method defined in +PostsController+, if you refresh "http://localhost:3000/posts/new":http://localhost:3000/posts/new you'll see another error:
-!images/getting_started/template_is_missing_posts_new.png(Template is missing for posts/new)
+!images/getting_started/template_is_missing_posts_new.png(Template is missing for posts/new)!
You're getting this error now because Rails expects plain actions like this one to have views associated with them to display their information. With no view available, Rails errors out.
@@ -284,13 +280,13 @@ Missing template posts/new, application/new with {:locale=>[:en], :formats=>[:ht
That's quite a lot of text! Let's quickly go through and understand what each part of it does.
-The first part identifies what template is missing. In this case, it's the +posts/new+ template. Rails will first look for this template. If it can't find it, then it will attempt to load a template called +application/new+. It looks for one here because the +PostsController+ inherits from +ApplicationController+.
+The first part identifies what template is missing. In this case, it's the +posts/new+ template. Rails will first look for this template. If not found, then it will attempt to load a template called +application/new+. It looks for one here because the +PostsController+ inherits from +ApplicationController+.
-The next part of the message contains a hash. The +:locale+ key in this hash simply indicates what spoken language template should be retrieved. By default, this is the English -- or "en" -- template. The next key, +:formats+ shows what formats of template Rails is after. The default is +:html+, and so Rails is looking for an HTML template. The final key, +:handlers+, is telling us what _template handlers_ could be used to render our template. +:erb+ is most commonly used for HTML templates, +:builder+ is used for XML templates, and +:coffee+ uses CoffeeScript to build JavaScript templates.
+The next part of the message contains a hash. The +:locale+ key in this hash simply indicates what spoken language template should be retrieved. By default, this is the English -- or "en" -- template. The next key, +:formats+ specifies the format of template to be served in response . The default format is +:html+, and so Rails is looking for an HTML template. The final key, +:handlers+, is telling us what _template handlers_ could be used to render our template. +:erb+ is most commonly used for HTML templates, +:builder+ is used for XML templates, and +:coffee+ uses CoffeeScript to build JavaScript templates.
The final part of this message tells us where Rails has looked for the templates. Templates within a basic Rails application like this are kept in a single location, but in more complex applications it could be many different paths.
-The simplest template that would work in this case would be one located at +app/views/posts/new.html.erb+. The extension of this file name is key: the first extension is the _format_ of the template, and the second extension is the _handler_ that will be used. Rails is attempting to find a template called +posts/new+ within +app/views+ for the application. The format for this template can only be +html+ and the handler must be one of +erb+, +builder+ or +coffee+. Because you want to create a new HTML form, you will be using the +ERB+ language. Therefore the file should be called +posts/new.html.erb+ and be located inside the +app/views+ directory of the application.
+The simplest template that would work in this case would be one located at +app/views/posts/new.html.erb+. The extension of this file name is key: the first extension is the _format_ of the template, and the second extension is the _handler_ that will be used. Rails is attempting to find a template called +posts/new+ within +app/views+ for the application. The format for this template can only be +html+ and the handler must be one of +erb+, +builder+ or +coffee+. Because you want to create a new HTML form, you will be using the +ERB+ language. Therefore the file should be called +posts/new.html.erb+ and needs to be located inside the +app/views+ directory of the application.
Go ahead now and create a new file at +app/views/posts/new.html.erb+ and write this content in it:
@@ -302,7 +298,9 @@ When you refresh "http://localhost:3000/posts/new":http://localhost:3000/posts/n
h4. The first form
-To create a form within this template, you will use a _form builder_. The primary form builder for Rails is provided by a helper method called +form_for+. To use this method, write this code into +app/views/posts/new.html.erb+:
+To create a form within this template, you will use a <em>form
+builder</em>. The primary form builder for Rails is provided by a helper
+method called +form_for+. To use this method, add this code into +app/views/posts/new.html.erb+:
<erb>
<%= form_for :post do |f| %>
@@ -346,7 +344,7 @@ By using the +post+ method rather than the +get+ method, Rails will define a rou
With the form and the route for it defined now, you will be able to fill in the form and then click the submit button to begin the process of creating a new post, so go ahead and do that. When you submit the form, you should see a familiar error:
-!images/getting_started/unknown_action_create_for_posts(Unknown action create for PostsController)!
+!images/getting_started/unknown_action_create_for_posts.png(Unknown action create for PostsController)!
You will now need to create the +create+ action within the +PostsController+ for this to work.
@@ -385,25 +383,44 @@ If you re-submit the form one more time you'll now no longer get the missing tem
This action is now displaying the parameters for the post that are coming in from the form. However, this isn't really all that helpful. Yes, you can see the parameters but nothing in particular is being done with them.
+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:
+
+<shell>
+$ rails generate model Post title:string text:text
+</shell>
+
+With that command we told Rails that we want a +Post+ model, which in
+turn should have a title attribute of type string, and a text attribute
+of type text. Rails in turn responded by creating a bunch of files. For
+now, we're only interested in +app/models/post.rb+ and
++db/migrate/20120419084633_create_posts.rb+. The latter is responsible
+for creating the database structure, which is what we'll look at next.
+
h4. Running a Migration
-One of the products of the +rails generate scaffold+ command is a _database
-migration_. Migrations are Ruby classes that are designed to make it simple to
+As we've just seen, +rails generate model+ created a _database
+migration_ file inside the +db/migrate+ directory.
+Migrations are Ruby classes that are designed to make it simple to
create and modify database tables. Rails uses rake commands to run migrations,
and it's possible to undo a migration after it's been applied to your database.
Migration filenames include a timestamp to ensure that they're processed in the
order that they were created.
-If you look in the +db/migrate/20100207214725_create_posts.rb+ file (remember,
+If you look in the +db/migrate/20120419084633_create_posts.rb+ file (remember,
yours will have a slightly different name), here's what you'll find:
<ruby>
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
- t.string :name
t.string :title
- t.text :content
+ t.text :text
t.timestamps
end
@@ -415,7 +432,7 @@ The above migration creates a method named +change+ which will be called when yo
run this migration. The action defined in this method is also reversible, which
means Rails knows how to reverse the change made by this migration, in case you
want to reverse it later. When you run this migration it will create a
-+posts+ table with two string columns and a text column. It also creates two
++posts+ table with one string column and a text column. It also creates two
timestamp fields to allow Rails to track post creation and update times. More
information about Rails migrations can be found in the "Rails Database
Migrations":migrations.html guide.
@@ -442,41 +459,191 @@ command will apply to the database defined in the +development+ section of your
environment, for instance in production, you must explicitly pass it when
invoking the command: <tt>rake db:migrate RAILS_ENV=production</tt>.
-h4. Adding a Link
+h4. Saving data in the controller
+
+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:
+
+<ruby>
+def create
+ @post = Post.new(params[:post])
+
+ @post.save
+ redirect_to :action => :show, :id => @post.id
+end
+</ruby>
+
+Here's what's going on: every Rails model can be initialized with its
+respective attributes, which are automatically mapped to its
+database columns. In the first line we do just that (remember that
++params[:post]+ contains the attributes we're interested in). Then,
++@post.save+ is responsible for saving the model in the database.
+Finally, on the last line we redirect the user to the +show+ action,
+wich we have not defined yet.
+
+TIP: As we'll see later, +@post.save+ returns a boolean indicating
+wherever the model was saved or not, and you can (and usually do) take
+different actions depending on the result of calling +@post.save+.
+
+h4. Showing posts
+
+Before trying to create a new post, let's add the +show+ action, which
+will be responsible for showing our posts. Open +config/routes.rb+
+and add the following route:
+
+<ruby>
+get "posts/:id" => "posts#show"
+</ruby>
+
+The special syntax +:id+ tells rails that this route expects an +:id+
+parameter, which in our case will be the id of the post. Note that this
+time we had to specify the actual mapping, +posts#show+ because
+otherwise Rails would not know which action to render.
+
+As we did before, we need to add the +show+ action in the
++posts_controller+ and its respective view.
+
+<ruby>
+def show
+ @post = Post.find(params[:id])
+end
+</ruby>
+
+A couple of things to note. We use +Post.find+ to find the post we're
+interested in. We also use an instance variable (prefixed by +@+) to
+hold a reference to the post object. We do this because Rails will pass all instance
+variables to the view.
+
+Now, create a new file +app/view/posts/show.html.erb+ with the following
+content:
+
+<erb>
+<p>
+ <strong>Title:</strong>
+ <%= @post.title %>
+</p>
+
+<p>
+ <strong>Text:</strong>
+ <%= @post.text %>
+</p>
+</erb>
+
+Finally, if you now go to
+"http://localhost:3000/posts/new":http://localhost:3000/posts/new you'll
+be able to create a post. Try it!
-To hook the posts up to the home page you've already created, you can add a link
-to the home page. Open +app/views/welcome/index.html.erb+ and modify it as follows:
+!images/getting_started/show_action_for_posts.png(Show action for posts)!
+
+h4. Listing all posts
+
+We still need a way to list all our posts, so let's do that. As usual,
+we'll need a route, a controller action, and a view:
+
+<ruby>
+# Add to config/routes.rb
+get "posts" => "posts#index"
+
+# Add to app/controllers/posts_controller.rb
+def index
+ @posts = Post.all
+end
+</ruby>
+
++app/view/posts/index.html.erb+:
+
+<erb>
+<h1>Listing posts</h1>
+
+<table>
+ <tr>
+ <th>Title</th>
+ <th>Text</th>
+ </tr>
+
+<% @posts.each do |post| %>
+ <tr>
+ <td><%= post.title %></td>
+ <td><%= post.text %></td>
+ </tr>
+<% end %>
+</table>
+</erb>
+
+h4. Adding links
+
+You can now create, show, and list posts. Now let's add some links to
+navigate through pages.
+
+Open +app/views/welcome/index.html.erb+ and modify it as follows:
<ruby>
<h1>Hello, Rails!</h1>
-<%= link_to "My Blog", posts_path %>
+<%= link_to "My Blog", :controller => "posts" %>
</ruby>
The +link_to+ method is one of Rails' built-in view helpers. It creates a
hyperlink based on text to display and where to go - in this case, to the path
for posts.
-h4. Working with Posts in the Browser
+Let's add links to the other views as well.
+
+<erb>
+# app/views/posts/index.html.erb
+
+<h1>Listing posts</h1>
+
+<%= link_to 'New post', :action => :new %>
+
+<table>
+ <tr>
+ <th>Title</th>
+ <th>Text</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>
+ </tr>
+<% end %>
+</table>
+
+# app/views/posts/new.html.erb
+
+<%= form_for :post do |f| %>
+ ...
+<% end %>
+
+<%= link_to 'Back', :action => :index %>
+
+# app/views/posts/show.html.erb
+
+<p>
+ <strong>Title:</strong>
+ <%= @post.title %>
+</p>
-Now you're ready to start working with posts. To do that, navigate to
-"http://localhost:3000":http://localhost:3000/ and then click the "My Blog"
-link:
+<p>
+ <strong>Text:</strong>
+ <%= @post.text %>
+</p>
-!images/posts_index.png(Posts Index screenshot)!
+<%= link_to 'Back', :action => :index %>
+</erb>
-This is the result of Rails rendering the +index+ view of your posts. There
-aren't currently any posts in the database, but if you click the +New Post+ link
-you can create one. After that, you'll find that you can edit posts, look at
-their details, or destroy them. All of the logic and HTML to handle this was
-built by the single +rails generate scaffold+ command.
+TIP: If you want to link to an action in the same controller, you don't
+need to specify the +:controller+ option, as Rails will use the current
+controller by default.
TIP: In development mode (which is what you're working in by default), Rails
reloads your application with every browser request, so there's no need to stop
-and restart the web server.
-
-Congratulations, you're riding the rails! Now it's time to see how it all works.
+and restart the web server when a change is made.
-h4. The Model
+h4. Adding Some Validation
The model file, +app/models/post.rb+ is about as simple as it can get:
@@ -491,24 +658,442 @@ your Rails models for free, including basic database CRUD (Create, Read, Update,
Destroy) operations, data validation, as well as sophisticated search support
and the ability to relate multiple models to one another.
-h4. Adding Some Validation
-
Rails includes methods to help you validate the data that you send to models.
Open the +app/models/post.rb+ file and edit it:
<ruby>
class Post < ActiveRecord::Base
- validates :name, :presence => true
validates :title, :presence => true,
:length => { :minimum => 5 }
end
</ruby>
-These changes will ensure that all posts have a name and a title, and that the
-title is at least five characters long. Rails can validate a variety of
-conditions in a model, including the presence or uniqueness of columns, their
+These changes will ensure that all posts have a title that is at least five characters long.
+Rails can validate a variety of conditions in a model, including the presence or uniqueness of columns, their
format, and the existence of associated objects. Validations are covered in detail
-in "Active Record Validations and Callbacks":active_record_validations_callbacks.html#validations-overview
+in "Active Record Validations and
+Callbacks":active_record_validations_callbacks.html#validations-overview
+
+If you open +posts_controller+ again, you'll notice that we don't check
+the result of calling +@post.save+. We need to change its behavior to
+show the form back to the user if any error occur:
+
+<ruby>
+def new
+ @post = Post.new
+end
+
+def create
+ @post = Post.new(params[:post])
+
+ if @post.save
+ redirect_to :action => :show, :id => @post.id
+ else
+ render 'new'
+ end
+end
+</ruby>
+
+Notice that I've also added +@post = Post.new+ to the +new+ action. I'll
+explain why I did that in the next section, for now add that to your
+controller as well.
+
+Also notice that we use +render+ instead of +redirect_to+ when +save+
+returns false. We can use +render+ so that the +@post+ object is passed
+back to the view.
+
+If you reload
+"http://localhost:3000/posts/new":http://localhost:3000/posts/new and
+try to save a post without a title, Rails will send you back to the
+form, but that's not very useful. You need to tell the user that
+something went wrong. To do that, you'll modify
++app/views/posts/index.html.erb+ to check for error messages:
+
+<erb>
+<%= form_for :post, :url => { :action => :create } 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 %>
+
+<%= link_to 'Back', :action => :index %>
+</erb>
+
+A few things are going on. We check if there are any errors with
++@post.errors.any?+, and in that case we show a list of all
+errors with +@post.errors.full_messages+.
+
++pluralize+ is a rails helper
+that takes a number and a string as its arguments. If the number is
+greater than one, the string will be automatically pluralized.
+
+The reason why we added +@post = Post.new+ in +posts_controller+ is that
+otherwise +@post+ would be +nil+ in our view, and calling
++@post.errors.any?+ would throw an error.
+
+TIP: Rails automatically wraps fields that contain an error with a div
+with class +field_with_errors+. You can define a css rule to make them
+standout.
+
+Now you'll get a nice error message when saving a post without title:
+
+!images/getting_started/form_with_errors.png(Form With Errors)!
+
+h4. Updating Posts
+
+We've covered the "CR" part of CRUD. Now let's focus on the "U" part,
+updating posts.
+
+The first step we'll take is adding a +edit+ action to
++posts_controller+.
+
+Start by adding a route to +config/routes.rb+:
+
+<ruby>
+get "posts/:id/edit" => "posts#edit"
+</ruby>
+
+And then add the controller action:
+
+<ruby>
+def edit
+ @post = Post.find(params[:id])
+end
+</ruby>
+
+The view will contain a form similar to the one we used when creating
+new posts. Create a file called +app/views/posts/edit.html.erb+ and make
+it look as follows:
+
+<erb>
+<h1>Editing post</h1>
+
+<%= form_for :post, :url => { :action => :update, :id => @post.id },
+:method => :put 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 %>
+
+<%= link_to 'Back', :action => :index %>
+</erb>
+
+This time we point the form to the +update+ action (not defined yet).
+The +:method => :put+ option tells Rails that we want this form to be
+submitted via +put+, which is the http method you're expected to use to
+*update* resources according to the REST protocol.
+
+TIP: By default forms built with the +form_for_ helper are sent via +POST+.
+
+Moving on, we need to add the +update+ action. The file
++config/routes.rb+ will need just one more line:
+
+<ruby>
+put "posts/:id" => "posts#update"
+</ruby>
+
+And the +update+ action in +posts_controller+ itself should not look too complicated by now:
+
+<ruby>
+def update
+ @post = Post.find(params[:id])
+
+ if @post.update_attributes(params[:post])
+ redirect_to :action => :show, :id => @post.id
+ else
+ render 'edit'
+ end
+end
+</ruby>
+
+The new method +update_attributes+ is used when you want to update a record
+that already exists, and it accepts an hash containing the attributes
+that you want to update. As before, if there was an error updating the
+post we want to show the form back to the user.
+
+TIP: you don't need to pass all attributes to +update_attributes+. For
+example, if you'd call +@post.update_attributes(:title => 'A new title')+
+Rails would only update the +title+ attribute, leaving all other
+attributes untouched.
+
+Finally, we want to show a link to the +edit+ action in the +index+ and
++show+ views:
+
+<erb>
+# app/view/posts/index.html.erb
+
+<table>
+ <tr>
+ <th>Title</th>
+ <th>Text</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>
+ </tr>
+<% end %>
+</table>
+
+# app/view/posts/show.html.erb
+
+...
+
+<%= link_to 'Back', :action => :index %>
+| <%= link_to 'Edit', :action => :edit, :id => @post.id %>
+</erb>
+
+And here's how our app looks so far:
+
+!images/getting_started/index_action_with_edit_link.png(Index action
+with edit link)!
+
+h4. Using partials to clean up duplication in views
+
++partials+ are what Rails uses to remove duplication in views. Here's a
+simple example:
+
+<erb>
+# app/views/user/show.html.erb
+
+<h1><%= @user.name %></h1>
+
+<%= render 'user_details' %>
+
+# app/views/user/_user_details.html.erb
+
+<%= @user.location %>
+
+<%= @user.about_me %>
+</erb>
+
+The +show+ view will automatically include the content of the
++_user_details+ view. Note that partials are prefixed by an underscore,
+as to not be confused with regular views. However, you don't include the
+underscore when including them with the +helper+ method.
+
+TIP: You can read more about partials in the "Layouts and Rendering in
+Rails":layouts_and_rendering.html guide.
+
+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
diff --git a/guides/source/i18n.textile b/guides/source/i18n.textile
index 320f1e9d20..6179694c40 100644
--- a/guides/source/i18n.textile
+++ b/guides/source/i18n.textile
@@ -866,19 +866,35 @@ The I18n API will catch all of these exceptions when they are thrown in the back
The reason for this is that during development you'd usually want your views to still render even though a translation is missing.
-In other contexts you might want to change this behaviour, though. E.g. the default exception handling does not allow to catch missing translations during automated tests easily. For this purpose a different exception handler can be specified. The specified exception handler must be a method on the I18n module:
+In other contexts you might want to change this behaviour, though. E.g. the default exception handling does not allow to catch missing translations during automated tests easily. For this purpose a different exception handler can be specified. The specified exception handler must be a method on the I18n module or a class with +#call+ method:
<ruby>
module I18n
- def self.just_raise_that_exception(*args)
- raise args.first
+ class JustRaiseExceptionHandler < ExceptionHandler
+ def call(exception, locale, key, options)
+ if exception.is_a?(MissingTranslation)
+ raise exception.to_exception
+ else
+ super
+ end
+ end
end
end
-I18n.exception_handler = :just_raise_that_exception
+I18n.exception_handler = I18n::JustRaiseExceptionHandler.new
</ruby>
-This would re-raise all caught exceptions including +MissingTranslationData+.
+This would re-raise only the +MissingTranslationData+ exception, passing all other input to the default exception handler.
+
+However, if you are using +I18n::Backend::Pluralization+ this handler will also raise +I18n::MissingTranslationData: translation missing: en.i18n.plural.rule+ exception that should normally be ignored to fall back to the default pluralization rule for English locale. To avoid this you may use additional check for translation key:
+
+<ruby>
+if exception.is_a?(MissingTranslation) && key.to_s != 'i18n.plural.rule'
+ raise exception.to_exception
+else
+ super
+end
+</ruby>
Another example where the default behaviour is less desirable is the Rails TranslationHelper which provides the method +#t+ (as well as +#translate+). When a +MissingTranslationData+ exception occurs in this context, the helper wraps the message into a span with the CSS class +translation_missing+.
diff --git a/guides/source/layout.html.erb b/guides/source/layout.html.erb
index 35b6fc7014..0a8daf7ae5 100644
--- a/guides/source/layout.html.erb
+++ b/guides/source/layout.html.erb
@@ -14,6 +14,8 @@
<link rel="stylesheet" type="text/css" href="stylesheets/syntaxhighlighter/shThemeRailsGuides.css" />
<link rel="stylesheet" type="text/css" href="stylesheets/fixes.css" />
+
+<link href="images/favicon.ico" rel="shortcut icon" type="image/x-icon" />
</head>
<body class="guide">
<% if @edge %>
diff --git a/guides/source/layouts_and_rendering.textile b/guides/source/layouts_and_rendering.textile
index 4b4f9f3745..f69afaa281 100644
--- a/guides/source/layouts_and_rendering.textile
+++ b/guides/source/layouts_and_rendering.textile
@@ -686,7 +686,7 @@ You can specify a full path relative to the document root, or a URL, if you pref
Rails will then output a +script+ tag such as this:
<html>
-<script src='/assets/main.js' type="text/javascript"></script>
+<script src='/assets/main.js'></script>
</html>
The request to this asset is then served by the Sprockets gem.
@@ -718,8 +718,8 @@ If the application does not use the asset pipeline, the +:defaults+ option loads
Outputting +script+ tags such as this:
<html>
-<script src="/javascripts/jquery.js" type="text/javascript"></script>
-<script src="/javascripts/jquery_ujs.js" type="text/javascript"></script>
+<script src="/javascripts/jquery.js"></script>
+<script src="/javascripts/jquery_ujs.js"></script>
</html>
These two files for jQuery, +jquery.js+ and +jquery_ujs.js+ must be placed inside +public/javascripts+ if the application doesn't use the asset pipeline. These files can be downloaded from the "jquery-rails repository on GitHub":https://github.com/indirect/jquery-rails/tree/master/vendor/assets/javascripts
@@ -805,7 +805,7 @@ To include +http://example.com/main.css+:
<%= stylesheet_link_tag "http://example.com/main.css" %>
</erb>
-By default, the +stylesheet_link_tag+ creates links with +media="screen" rel="stylesheet" type="text/css"+. You can override any of these defaults by specifying an appropriate option (+:media+, +:rel+, or +:type+):
+By default, the +stylesheet_link_tag+ creates links with +media="screen" rel="stylesheet"+. You can override any of these defaults by specifying an appropriate option (+:media+, +:rel+):
<erb>
<%= stylesheet_link_tag "main_print", :media => "print" %>
@@ -1134,13 +1134,6 @@ In Rails 3.0, there is also a shorthand for this. Assuming +@products+ is a coll
Rails determines the name of the partial to use by looking at the model name in the collection. In fact, you can even create a heterogeneous collection and render it this way, and Rails will choose the proper partial for each member of the collection:
-In the event that the collection is empty, +render+ will return nil, so it should be fairly simple to provide alternative content.
-
-<erb>
-<h1>Products</h1>
-<%= render(@products) || 'There are no products available.' %>
-</erb>
-
* +index.html.erb+
<erb>
@@ -1162,6 +1155,13 @@ In the event that the collection is empty, +render+ will return nil, so it shoul
In this case, Rails will use the customer or employee partials as appropriate for each member of the collection.
+In the event that the collection is empty, +render+ will return nil, so it should be fairly simple to provide alternative content.
+
+<erb>
+<h1>Products</h1>
+<%= render(@products) || 'There are no products available.' %>
+</erb>
+
h5. Local Variables
To use a custom local variable name within the partial, specify the +:as+ option in the call to the partial:
@@ -1193,6 +1193,16 @@ h5. Spacer Templates
Rails will render the +_product_ruler+ partial (with no data passed in to it) between each pair of +_product+ partials.
+h5. Partial Layouts
+
+When rendering collections it is also possible to use the +:layout+ option:
+
+<erb>
+<%= render :partial => "product", :collection => @products, :layout => "special_layout" %>
+</erb>
+
+The layout will be rendered together with the partial for each item in the collection. The current object and object_counter variables will be available in the layout as well, the same way they do within the partial.
+
h4. Using Nested Layouts
You may find that your application requires a layout that differs slightly from your regular application layout to support one particular controller. Rather than repeating the main layout and editing it, you can accomplish this by using nested layouts (sometimes called sub-templates). Here's an example:
@@ -1206,7 +1216,7 @@ Suppose you have the following +ApplicationController+ layout:
<head>
<title><%= @page_title or 'Page Title' %></title>
<%= stylesheet_link_tag 'layout' %>
- <style type="text/css"><%= yield :stylesheets %></style>
+ <style><%= yield :stylesheets %></style>
</head>
<body>
<div id="top_menu">Top menu items here</div>
diff --git a/guides/source/migrations.textile b/guides/source/migrations.textile
index c11f8e221b..f855072fd8 100644
--- a/guides/source/migrations.textile
+++ b/guides/source/migrations.textile
@@ -51,7 +51,7 @@ end
This migration adds a table called +products+ with a string column called +name+
and a text column called +description+. A primary key column called +id+ will
-also be added, however since this is the default we do not need to ask for this.
+also be added, however since this is the default we do not need to explicitly specify it.
The timestamp columns +created_at+ and +updated_at+ which Active Record
populates automatically will also be added. Reversing this migration is as
simple as dropping the table.
@@ -65,7 +65,7 @@ class AddReceiveNewsletterToUsers < ActiveRecord::Migration
change_table :users do |t|
t.boolean :receive_newsletter, :default => false
end
- User.update_all ["receive_newsletter = ?", true]
+ User.update_all :receive_newsletter => true
end
def down
@@ -82,6 +82,8 @@ it to default to +false+ for new users, but existing users are considered to
have already opted in, so we use the User model to set the flag to +true+ for
existing users.
+h4. Using the change method
+
Rails 3.1 makes migrations smarter by providing a new <tt>change</tt> method.
This method is preferred for writing constructive migrations (adding columns or
tables). The migration knows how to migrate your database and reverse it when
@@ -475,7 +477,16 @@ end
</ruby>
will add an +attachment_id+ column and a string +attachment_type+ column with
-a default value of 'Photo'.
+a default value of 'Photo'. +references+ also allows you to define an
+index directly, instead of using +add_index+ after the +create_table+ call:
+
+<ruby>
+create_table :products do |t|
+ t.references :category, :index => true
+end
+</ruby>
+
+will create an index identical to calling `add_index :products, :category_id`.
NOTE: The +references+ helper does not actually create foreign key constraints
for you. You will need to use +execute+ or a plugin that adds "foreign key
@@ -497,7 +508,7 @@ and
h4. Using the +change+ Method
The +change+ method removes the need to write both +up+ and +down+ methods in
-those cases that Rails know how to revert the changes automatically. Currently,
+those cases that Rails knows how to revert the changes automatically. Currently,
the +change+ method supports only these migration definitions:
* +add_column+
@@ -635,10 +646,9 @@ example,
$ rake db:migrate:up VERSION=20080906120000
</shell>
-will run the +up+ method from the 20080906120000 migration. These tasks still
-check whether the migration has already run, so for example +db:migrate:up
-VERSION=20080906120000+ will do nothing if Active Record believes that
-20080906120000 has already been run.
+will run the +up+ method from the 20080906120000 migration. This task will first
+check whether the migration is already performed and will do nothing if Active Record believes
+that it has already been run.
h4. Changing the output of running migrations
@@ -728,7 +738,7 @@ class AddFlagToProduct < ActiveRecord::Migration
def change
add_column :products, :flag, :boolean
Product.all.each do |product|
- product.update_attributes!(:flag => 'false')
+ product.update_attributes!(:flag => false)
end
end
end
@@ -771,7 +781,7 @@ Both migrations work for Alice.
Bob comes back from vacation and:
-# Updates the source - which contains both migrations and the latests version of
+# Updates the source - which contains both migrations and the latest version of
the Product model.
# Runs outstanding migrations with +rake db:migrate+, which
includes the one that updates the +Product+ model.
@@ -804,7 +814,7 @@ class AddFlagToProduct < ActiveRecord::Migration
end
def change
- add_column :products, :flag, :integer
+ add_column :products, :flag, :boolean
Product.reset_column_information
Product.all.each do |product|
product.update_attributes!(:flag => false)
diff --git a/guides/source/plugins.textile b/guides/source/plugins.textile
index 97b4eca779..95e38db483 100644
--- a/guides/source/plugins.textile
+++ b/guides/source/plugins.textile
@@ -25,16 +25,14 @@ endprologue.
h3. Setup
-Before you continue, take a moment to decide if your new plugin will be potentially shared across different Rails applications.
+_"vendored plugins"_ were available in previous versions of Rails, but they are deprecated in
+Rails 3.2, and will not be available in the future.
-* If your plugin is specific to your application, your new plugin will be a _vendored plugin_.
-* If you think your plugin may be used across applications, build it as a _gemified plugin_.
+Currently, Rails plugins are built as gems, _gemified plugins_. They can be shared accross
+different rails applications using RubyGems and Bundler if desired.
h4. Generate a gemified plugin.
-Writing your Rails plugin as a gem, rather than as a vendored plugin,
- lets you share your plugin across different rails applications using
- RubyGems and Bundler.
Rails 3.1 ships with a +rails plugin new+ command which creates a
skeleton for developing any kind of Rails extension with the ability
diff --git a/guides/source/rails_on_rack.textile b/guides/source/rails_on_rack.textile
index 9526526bc7..ff862273fd 100644
--- a/guides/source/rails_on_rack.textile
+++ b/guides/source/rails_on_rack.textile
@@ -91,13 +91,15 @@ For a freshly generated Rails application, this might produce something like:
<ruby>
use ActionDispatch::Static
use Rack::Lock
-use ActiveSupport::Cache::Strategy::LocalCache
+use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x000000029a0838>
use Rack::Runtime
+use Rack::MethodOverride
+use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
-use Rack::Sendfile
+use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
@@ -105,8 +107,9 @@ use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
-use Rack::MethodOverride
use ActionDispatch::Head
+use Rack::ConditionalGet
+use Rack::ETag
use ActionDispatch::BestStandardsSupport
run Blog::Application.routes
</ruby>
@@ -145,62 +148,104 @@ You can swap an existing middleware in the middleware stack using +config.middle
<ruby>
# config/application.rb
-# Replace ActionController::Failsafe with Lifo::Failsafe
-config.middleware.swap ActionController::Failsafe, Lifo::Failsafe
+# Replace ActionDispatch::ShowExceptions with Lifo::ShowExceptions
+config.middleware.swap ActionDispatch::ShowExceptions, Lifo::ShowExceptions
</ruby>
h5. Middleware Stack is an Array
The middleware stack behaves just like a normal +Array+. You can use any +Array+ methods to insert, reorder, or remove items from the stack. Methods described in the section above are just convenience methods.
-For example, the following removes the middleware matching the supplied class name:
+Append following lines to your application configuration:
<ruby>
-config.middleware.delete(middleware)
+# config/application.rb
+config.middleware.delete "Rack::Lock"
</ruby>
+And now if you inspect the middleware stack, you'll find that +Rack::Lock+ will not be part of it.
+
+<shell>
+$ rake middleware
+(in /Users/lifo/Rails/blog)
+use ActionDispatch::Static
+use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x00000001c304c8>
+use Rack::Runtime
+...
+run Myapp::Application.routes
+</shell>
+
h4. Internal Middleware Stack
-Much of Action Controller's functionality is implemented as Middlewares. The following table explains the purpose of each of them:
+Much of Action Controller's functionality is implemented as Middlewares. The following list explains the purpose of each of them:
-|_.Middleware|_.Purpose|
-|+Rack::Lock+|Sets <tt>env["rack.multithread"]</tt> flag to +true+ and wraps the application within a Mutex.|
-|+ActionController::Failsafe+|Returns HTTP Status +500+ to the client if an exception gets raised while dispatching.|
-|+ActiveRecord::QueryCache+|Enables the Active Record query cache.|
-|+ActionDispatch::Session::CookieStore+|Uses the cookie based session store.|
-|+ActionDispatch::Session::CacheStore+|Uses the Rails cache based session store.|
-|+ActionDispatch::Session::MemCacheStore+|Uses the memcached based session store.|
-|+ActiveRecord::SessionStore+|Uses the database based session store.|
-|+Rack::MethodOverride+|Sets HTTP method based on +_method+ parameter or <tt>env["HTTP_X_HTTP_METHOD_OVERRIDE"]</tt>.|
-|+Rack::Head+|Discards the response body if the client sends a +HEAD+ request.|
+ *+ActionDispatch::Static+*
+* Used to serve static assets. Disabled if <tt>config.serve_static_assets</tt> is true.
-TIP: It's possible to use any of the above middlewares in your custom Rack stack.
+ *+Rack::Lock+*
+* Sets <tt>env["rack.multithread"]</tt> flag to +true+ and wraps the application within a Mutex.
-h4. Customizing Internal Middleware Stack
+ *+ActiveSupport::Cache::Strategy::LocalCache::Middleware+*
+* Used for memory caching. This cache is not thread safe.
-It's possible to replace the entire middleware stack with a custom stack using <tt>ActionController::Dispatcher.middleware=</tt>.
+ *+Rack::Runtime+*
+* Sets an X-Runtime header, containing the time (in seconds) taken to execute the request.
-Put the following in an initializer:
+ *+Rack::MethodOverride+*
+* Allows the method to be overridden if <tt>params[:_method]</tt> is set. This is the middleware which supports the PUT and DELETE HTTP method types.
-<ruby>
-# config/initializers/stack.rb
-ActionController::Dispatcher.middleware = ActionController::MiddlewareStack.new do |m|
- m.use ActionController::Failsafe
- m.use ActiveRecord::QueryCache
- m.use Rack::Head
-end
-</ruby>
+ *+ActionDispatch::RequestId+*
+* Makes a unique +X-Request-Id+ header available to the response and enables the <tt>ActionDispatch::Request#uuid</tt> method.
-And now inspecting the middleware stack:
+ *+Rails::Rack::Logger+*
+* Notifies the logs that the request has began. After request is complete, flushes all the logs.
-<shell>
-$ rake middleware
-(in /Users/lifo/Rails/blog)
-use ActionController::Failsafe
-use ActiveRecord::QueryCache
-use Rack::Head
-run ActionController::Dispatcher.new
-</shell>
+ *+ActionDispatch::ShowExceptions+*
+* Rescues any exception returned by the application and calls an exceptions app that will wrap it in a format for the end user.
+
+ *+ActionDispatch::DebugExceptions+*
+* Responsible for logging exceptions and showing a debugging page in case the request is local.
+
+ *+ActionDispatch::RemoteIp+*
+* Checks for IP spoofing attacks.
+
+ *+ActionDispatch::Reloader+*
+* Provides prepare and cleanup callbacks, intended to assist with code reloading during development.
+
+ *+ActionDispatch::Callbacks+*
+* Runs the prepare callbacks before serving the request.
+
+ *+ActiveRecord::ConnectionAdapters::ConnectionManagement+*
+* Cleans active connections after each request, unless the <tt>rack.test</tt> key in the request environment is set to +true+.
+
+ *+ActiveRecord::QueryCache+*
+* Enables the Active Record query cache.
+
+ *+ActionDispatch::Cookies+*
+* Sets cookies for the request.
+
+ *+ActionDispatch::Session::CookieStore+*
+* Responsible for storing the session in cookies.
+
+ *+ActionDispatch::Flash+*
+* Sets up the flash keys. Only available if <tt>config.action_controller.session_store</tt> is set to a value.
+
+ *+ActionDispatch::ParamsParser+*
+* Parses out parameters from the request into <tt>params</tt>.
+
+ *+ActionDispatch::Head+*
+* Converts HEAD requests to +GET+ requests and serves them as so.
+
+ *+Rack::ConditionalGet+*
+* Adds support for "Conditional +GET+" so that server responds with nothing if page wasn't changed.
+
+ *+Rack::ETag+*
+* Adds ETag header on all String bodies. ETags are used to validate cache.
+
+ *+ActionDispatch::BestStandardsSupport+*
+* Enables “best standards support” so that IE8 renders some elements correctly.
+
+TIP: It's possible to use any of the above middlewares in your custom Rack stack.
h4. Using Rack Builder
diff --git a/guides/source/routing.textile b/guides/source/routing.textile
index e93b1280e0..836e0cdd70 100644
--- a/guides/source/routing.textile
+++ b/guides/source/routing.textile
@@ -25,7 +25,7 @@ GET /patients/17
it asks the router to match it to a controller action. If the first matching route is
<ruby>
-match "/patients/:id" => "patients#show"
+get "/patients/:id" => "patients#show"
</ruby>
the request is dispatched to the +patients+ controller's +show+ action with <tt>{ :id => "17" }</tt> in +params+.
@@ -121,7 +121,7 @@ h4. Singular Resources
Sometimes, you have a resource that clients always look up without referencing an ID. For example, you would like +/profile+ to always show the profile of the currently logged in user. In this case, you can use a singular resource to map +/profile+ (rather than +/profile/:id+) to the +show+ action.
<ruby>
-match "profile" => "users#show"
+get "profile" => "users#show"
</ruby>
This resourceful route
@@ -374,7 +374,7 @@ h4. Bound Parameters
When you set up a regular route, you supply a series of symbols that Rails maps to parts of an incoming HTTP request. Two of these symbols are special: +:controller+ maps to the name of a controller in your application, and +:action+ maps to the name of an action within that controller. For example, consider one of the default Rails routes:
<ruby>
-match ':controller(/:action(/:id))'
+get ':controller(/:action(/:id))'
</ruby>
If an incoming request of +/photos/show/1+ is processed by this route (because it hasn't matched any previous route in the file), then the result will be to invoke the +show+ action of the +PhotosController+, and to make the final parameter +"1"+ available as +params[:id]+. This route will also route the incoming request of +/photos+ to +PhotosController#index+, since +:action+ and +:id+ are optional parameters, denoted by parentheses.
@@ -384,7 +384,7 @@ h4. Dynamic Segments
You can set up as many dynamic segments within a regular route as you like. Anything other than +:controller+ or +:action+ will be available to the action as part of +params+. If you set up this route:
<ruby>
-match ':controller/:action/:id/:user_id'
+get ':controller/:action/:id/:user_id'
</ruby>
An incoming path of +/photos/show/1/2+ will be dispatched to the +show+ action of the +PhotosController+. +params[:id]+ will be +"1"+, and +params[:user_id]+ will be +"2"+.
@@ -392,7 +392,7 @@ An incoming path of +/photos/show/1/2+ will be dispatched to the +show+ action o
NOTE: You can't use +:namespace+ or +:module+ with a +:controller+ path segment. If you need to do this then use a constraint on :controller that matches the namespace you require. e.g:
<ruby>
-match ':controller(/:action(/:id))', :controller => /admin\/[^\/]+/
+get ':controller(/:action(/:id))', :controller => /admin\/[^\/]+/
</ruby>
TIP: By default dynamic segments don't accept dots - this is because the dot is used as a separator for formatted routes. If you need to use a dot within a dynamic segment add a constraint which overrides this - for example +:id+ => /[^\/]+/ allows anything except a slash.
@@ -402,7 +402,7 @@ h4. Static Segments
You can specify static segments when creating a route:
<ruby>
-match ':controller/:action/:id/with_user/:user_id'
+get ':controller/:action/:id/with_user/:user_id'
</ruby>
This route would respond to paths such as +/photos/show/1/with_user/2+. In this case, +params+ would be <tt>{ :controller => "photos", :action => "show", :id => "1", :user_id => "2" }</tt>.
@@ -412,7 +412,7 @@ h4. The Query String
The +params+ will also include any parameters from the query string. For example, with this route:
<ruby>
-match ':controller/:action/:id'
+get ':controller/:action/:id'
</ruby>
An incoming path of +/photos/show/1?user_id=2+ will be dispatched to the +show+ action of the +Photos+ controller. +params+ will be <tt>{ :controller => "photos", :action => "show", :id => "1", :user_id => "2" }</tt>.
@@ -422,7 +422,7 @@ h4. Defining Defaults
You do not need to explicitly use the +:controller+ and +:action+ symbols within a route. You can supply them as defaults:
<ruby>
-match 'photos/:id' => 'photos#show'
+get 'photos/:id' => 'photos#show'
</ruby>
With this route, Rails will match an incoming path of +/photos/12+ to the +show+ action of +PhotosController+.
@@ -430,7 +430,7 @@ With this route, Rails will match an incoming path of +/photos/12+ to the +show+
You can also define other defaults in a route by supplying a hash for the +:defaults+ option. This even applies to parameters that you do not specify as dynamic segments. For example:
<ruby>
-match 'photos/:id' => 'photos#show', :defaults => { :format => 'jpg' }
+get 'photos/:id' => 'photos#show', :defaults => { :format => 'jpg' }
</ruby>
Rails would match +photos/12+ to the +show+ action of +PhotosController+, and set +params[:format]+ to +"jpg"+.
@@ -440,49 +440,45 @@ h4. Naming Routes
You can specify a name for any route using the +:as+ option.
<ruby>
-match 'exit' => 'sessions#destroy', :as => :logout
+get 'exit' => 'sessions#destroy', :as => :logout
</ruby>
This will create +logout_path+ and +logout_url+ as named helpers in your application. Calling +logout_path+ will return +/exit+
h4. HTTP Verb Constraints
-You can use the +:via+ option to constrain the request to one or more HTTP methods:
+In general, you should use the +get+, +post+, +put+ and +delete+ methods to constrain a route to a particular verb. You can use the +match+ method with the +:via+ option to match multiple verbs at once:
<ruby>
-match 'photos/show' => 'photos#show', :via => :get
+match 'photos' => 'photos#show', :via => [:get, :post]
</ruby>
-There is a shorthand version of this as well:
+You can match all verbs to a particular route using +:via => :all+:
<ruby>
-get 'photos/show'
+match 'photos' => 'photos#show', :via => :all
</ruby>
-You can also permit more than one verb to a single route:
-
-<ruby>
-match 'photos/show' => 'photos#show', :via => [:get, :post]
-</ruby>
+You should avoid routing all verbs to an action unless you have a good reason to, as routing both +GET+ requests and +POST+ requests to a single action has security implications.
h4. Segment Constraints
You can use the +:constraints+ option to enforce a format for a dynamic segment:
<ruby>
-match 'photos/:id' => 'photos#show', :constraints => { :id => /[A-Z]\d{5}/ }
+get 'photos/:id' => 'photos#show', :constraints => { :id => /[A-Z]\d{5}/ }
</ruby>
This route would match paths such as +/photos/A12345+. You can more succinctly express the same route this way:
<ruby>
-match 'photos/:id' => 'photos#show', :id => /[A-Z]\d{5}/
+get 'photos/:id' => 'photos#show', :id => /[A-Z]\d{5}/
</ruby>
+:constraints+ takes regular expressions with the restriction that regexp anchors can't be used. For example, the following route will not work:
<ruby>
-match '/:id' => 'posts#show', :constraints => {:id => /^\d/}
+get '/:id' => 'posts#show', :constraints => {:id => /^\d/}
</ruby>
However, note that you don't need to use anchors because all routes are anchored at the start.
@@ -490,8 +486,8 @@ However, note that you don't need to use anchors because all routes are anchored
For example, the following routes would allow for +posts+ with +to_param+ values like +1-hello-world+ that always begin with a number and +users+ with +to_param+ values like +david+ that never begin with a number to share the root namespace:
<ruby>
-match '/:id' => 'posts#show', :constraints => { :id => /\d.+/ }
-match '/:username' => 'users#show'
+get '/:id' => 'posts#show', :constraints => { :id => /\d.+/ }
+get '/:username' => 'users#show'
</ruby>
h4. Request-Based Constraints
@@ -501,7 +497,7 @@ You can also constrain a route based on any method on the <a href="action_contro
You specify a request-based constraint the same way that you specify a segment constraint:
<ruby>
-match "photos", :constraints => {:subdomain => "admin"}
+get "photos", :constraints => {:subdomain => "admin"}
</ruby>
You can also specify constraints in a block form:
@@ -530,17 +526,28 @@ class BlacklistConstraint
end
TwitterClone::Application.routes.draw do
- match "*path" => "blacklist#index",
+ get "*path" => "blacklist#index",
:constraints => BlacklistConstraint.new
end
</ruby>
+You can also specify constraints as a lambda:
+
+<ruby>
+TwitterClone::Application.routes.draw do
+ get "*path" => "blacklist#index",
+ :constraints => lambda { |request| Blacklist.retrieve_ips.include?(request.remote_ip) }
+end
+</ruby>
+
+Both the +matches?+ method and the lambda gets the +request+ object as an argument.
+
h4. Route Globbing
Route globbing is a way to specify that a particular parameter should be matched to all the remaining parts of a route. For example
<ruby>
-match 'photos/*other' => 'photos#unknown'
+get 'photos/*other' => 'photos#unknown'
</ruby>
This route would match +photos/12+ or +/photos/long/path/to/12+, setting +params[:other]+ to +"12"+ or +"long/path/to/12"+.
@@ -548,7 +555,7 @@ This route would match +photos/12+ or +/photos/long/path/to/12+, setting +params
Wildcard segments can occur anywhere in a route. For example,
<ruby>
-match 'books/*section/:title' => 'books#show'
+get 'books/*section/:title' => 'books#show'
</ruby>
would match +books/some/section/last-words-a-memoir+ with +params[:section]+ equals +"some/section"+, and +params[:title]+ equals +"last-words-a-memoir"+.
@@ -556,7 +563,7 @@ would match +books/some/section/last-words-a-memoir+ with +params[:section]+ equ
Technically a route can have even more than one wildcard segment. The matcher assigns segments to parameters in an intuitive way. For example,
<ruby>
-match '*a/foo/*b' => 'test#index'
+get '*a/foo/*b' => 'test#index'
</ruby>
would match +zoo/woo/foo/bar/baz+ with +params[:a]+ equals +"zoo/woo"+, and +params[:b]+ equals +"bar/baz"+.
@@ -564,19 +571,19 @@ would match +zoo/woo/foo/bar/baz+ with +params[:a]+ equals +"zoo/woo"+, and +par
NOTE: Starting from Rails 3.1, wildcard routes will always match the optional format segment by default. For example if you have this route:
<ruby>
-match '*pages' => 'pages#show'
+get '*pages' => 'pages#show'
</ruby>
NOTE: By requesting +"/foo/bar.json"+, your +params[:pages]+ will be equals to +"foo/bar"+ with the request format of JSON. If you want the old 3.0.x behavior back, you could supply +:format => false+ like this:
<ruby>
-match '*pages' => 'pages#show', :format => false
+get '*pages' => 'pages#show', :format => false
</ruby>
NOTE: If you want to make the format segment mandatory, so it cannot be omitted, you can supply +:format => true+ like this:
<ruby>
-match '*pages' => 'pages#show', :format => true
+get '*pages' => 'pages#show', :format => true
</ruby>
h4. Redirection
@@ -584,20 +591,20 @@ h4. Redirection
You can redirect any path to another path using the +redirect+ helper in your router:
<ruby>
-match "/stories" => redirect("/posts")
+get "/stories" => redirect("/posts")
</ruby>
You can also reuse dynamic segments from the match in the path to redirect to:
<ruby>
-match "/stories/:name" => redirect("/posts/%{name}")
+get "/stories/:name" => redirect("/posts/%{name}")
</ruby>
You can also provide a block to redirect, which receives the params and (optionally) the request object:
<ruby>
-match "/stories/:name" => redirect {|params| "/posts/#{params[:name].pluralize}" }
-match "/stories" => redirect {|p, req| "/posts/#{req.subdomain}" }
+get "/stories/:name" => redirect {|params| "/posts/#{params[:name].pluralize}" }
+get "/stories" => redirect {|p, req| "/posts/#{req.subdomain}" }
</ruby>
Please note that this redirection is a 301 "Moved Permanently" redirect. Keep in mind that some web browsers or proxy servers will cache this type of redirect, making the old page inaccessible.
@@ -609,10 +616,10 @@ h4. Routing to Rack Applications
Instead of a String, like +"posts#index"+, which corresponds to the +index+ action in the +PostsController+, you can specify any <a href="rails_on_rack.html">Rack application</a> as the endpoint for a matcher.
<ruby>
-match "/application.js" => Sprockets
+match "/application.js" => Sprockets, :via => :all
</ruby>
-As long as +Sprockets+ responds to +call+ and returns a <tt>[status, headers, body]</tt>, the router won't know the difference between the Rack application and an action.
+As long as +Sprockets+ responds to +call+ and returns a <tt>[status, headers, body]</tt>, the router won't know the difference between the Rack application and an action. This is an appropriate use of +:via => :all+, as you will want to allow your Rack application to handle all verbs as it considers appropriate.
NOTE: For the curious, +"posts#index"+ actually expands out to +PostsController.action(:index)+, which returns a valid Rack application.
@@ -627,6 +634,8 @@ root 'pages#main' # shortcut for the above
You should put the +root+ route at the top of the file, because it is the most popular route and should be matched first. You also need to delete the +public/index.html+ file for the root route to take effect.
+NOTE: The +root+ route only routes +GET+ requests to the action.
+
h3. Customizing Resourceful Routes
While the default routes and helpers generated by +resources :posts+ will usually serve you well, you may want to customize them in some way. Rails allows you to customize virtually any generic part of the resourceful helpers.
@@ -820,6 +829,24 @@ end
This will create routing helpers such as +magazine_periodical_ads_url+ and +edit_magazine_periodical_ad_path+.
+h3. Breaking Up a Large Route File
+
+If you have a large route file that you would like to break up into multiple files, you can use the +#draw+ method in your router:
+
+<ruby>
+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:
+
+<ruby>
+# in config/routes/admin.rb
+
+namespace :admin do
+ resources :posts
+end
+</ruby>
+
h3. Inspecting and Testing Routes
Rails offers facilities for inspecting and testing your routes.
diff --git a/guides/source/ruby_on_rails_guides_guidelines.textile b/guides/source/ruby_on_rails_guides_guidelines.textile
index b141fab590..f3e934d38c 100644
--- a/guides/source/ruby_on_rails_guides_guidelines.textile
+++ b/guides/source/ruby_on_rails_guides_guidelines.textile
@@ -1,20 +1,20 @@
h2. Ruby on Rails Guides Guidelines
-This guide documents guidelines for writing guides. This guide follows itself in a gracile loop.
+This guide documents guidelines for writing Ruby on Rails Guides. This guide follows itself in a graceful loop, serving itself as an example.
endprologue.
h3. Textile
-Guides are written in "Textile":http://www.textism.com/tools/textile/. There's comprehensive documentation "here":http://redcloth.org/hobix.com/textile/ and a cheatsheet for markup "here":http://redcloth.org/hobix.com/textile/quick.html.
+Guides are written in "Textile":http://www.textism.com/tools/textile/. There is comprehensive "documentation":http://redcloth.org/hobix.com/textile/ and a "cheatsheet":http://redcloth.org/hobix.com/textile/quick.html for markup.
h3. Prologue
-Each guide should start with motivational text at the top (that's the little introduction in the blue area.) The prologue should tell the reader what the guide is about, and what they will learn. See for example the "Routing Guide":routing.html.
+Each guide should start with motivational text at the top (that's the little introduction in the blue area). The prologue should tell the reader what the guide is about, and what they will learn. See for example the "Routing Guide":routing.html.
h3. Titles
-The title of every guide uses +h2+, guide sections use +h3+, subsections +h4+, etc.
+The title of every guide uses +h2+; guide sections use +h3+; subsections +h4+; etc.
Capitalize all words except for internal articles, prepositions, conjunctions, and forms of the verb to be:
@@ -31,7 +31,7 @@ h6. The <tt>:content_type</tt> Option
h3. API Documentation Guidelines
-The guides and the API should be coherent where appropriate. Please have a look at these particular sections of the "API Documentation Guidelines":api_documentation_guidelines.html:
+The guides and the API should be coherent and consistent where appropriate. Please have a look at these particular sections of the "API Documentation Guidelines":api_documentation_guidelines.html:
* "Wording":api_documentation_guidelines.html#wording
* "Example Code":api_documentation_guidelines.html#example-code
@@ -55,16 +55,17 @@ bundle exec rake generate_guides
To process +my_guide.textile+ and nothing else use the +ONLY+ environment variable:
<plain>
+touch my_guide.textile
bundle exec rake generate_guides ONLY=my_guide
</plain>
By default, guides that have not been modified are not processed, so +ONLY+ is rarely needed in practice.
-To force process of all the guides, pass +ALL=1+.
+To force processing all the guides, pass +ALL=1+.
It is also recommended that you work with +WARNINGS=1+. This detects duplicate IDs and warns about broken internal links.
-If you want to generate guides in languages other than English, you can keep them in a separate directory under +source+ (eg. <tt>source/es</tt>) and use the +GUIDES_LANGUAGE+ environment variable:
+If you want to generate guides in a language other than English, you can keep them in a separate directory under +source+ (eg. <tt>source/es</tt>) and use the +GUIDES_LANGUAGE+ environment variable:
<plain>
bundle exec rake generate_guides GUIDES_LANGUAGE=es
@@ -78,11 +79,11 @@ Please validate the generated HTML with:
bundle exec rake validate_guides
</plain>
-Particularly, titles get an ID generated from their content and this often leads to duplicates. Please set +WARNINGS=1+ when generating guides to detect them. The warning messages suggest a way to fix them.
+Particularly, titles get an ID generated from their content and this often leads to duplicates. Please set +WARNINGS=1+ when generating guides to detect them. The warning messages suggest a solution.
h3. Kindle Guides
-h4. Generation
+h4(#generation-kindle). Generation
To generate guides for the Kindle, you need to provide +KINDLE=1+ as an environment variable:
diff --git a/guides/source/security.textile b/guides/source/security.textile
index 747a4d6791..c065529cac 100644
--- a/guides/source/security.textile
+++ b/guides/source/security.textile
@@ -385,7 +385,7 @@ params[:user] # => {:name => “ow3ned”, :admin => true}
So if you create a new user using mass-assignment, it may be too easy to become an administrator.
-Note that this vulnerability is not restricted to database columns. Any setter method, unless explicitly protected, is accessible via the <tt>attributes=</tt> method. In fact, this vulnerability is extended even further with the introduction of nested mass assignment (and nested object forms) in Rails 2.3<plus>. The +accepts_nested_attributes_for+ declaration provides us the ability to extend mass assignment to model associations (+has_many+, +has_one+, +has_and_belongs_to_many+). For example:
+Note that this vulnerability is not restricted to database columns. Any setter method, unless explicitly protected, is accessible via the <tt>attributes=</tt> method. In fact, this vulnerability is extended even further with the introduction of nested mass assignment (and nested object forms) in Rails 2.3. The +accepts_nested_attributes_for+ declaration provides us the ability to extend mass assignment to model associations (+has_many+, +has_one+, +has_and_belongs_to_many+). For example:
<ruby>
class Person < ActiveRecord::Base
diff --git a/guides/source/testing.textile b/guides/source/testing.textile
index c367f532ae..d35be6a70e 100644
--- a/guides/source/testing.textile
+++ b/guides/source/testing.textile
@@ -412,7 +412,7 @@ NOTE: +assert_valid(record)+ has been deprecated. Please use +assert(record.vali
|+assert_no_difference(expressions, message = nil, &amp;block)+ |Asserts that the numeric result of evaluating an expression is not changed before and after invoking the passed in block.|
|+assert_recognizes(expected_options, path, extras={}, message=nil)+ |Asserts that the routing of the given path was handled correctly and that the parsed options (given in the expected_options hash) match path. Basically, it asserts that Rails recognizes the route given by expected_options.|
|+assert_generates(expected_path, options, defaults={}, extras = {}, message=nil)+ |Asserts that the provided options can be used to generate the provided path. This is the inverse of assert_recognizes. The extras parameter is used to tell the request the names and values of additional request parameters that would be in a query string. The message parameter allows you to specify a custom error message for assertion failures.|
-|+assert_response(type, message = nil)+ |Asserts that the response comes with a specific status code. You can specify +:success+ to indicate 200, +:redirect+ to indicate 300-399, +:missing+ to indicate 404, or +:error+ to match the 500-599 range|
+|+assert_response(type, message = nil)+ |Asserts that the response comes with a specific status code. You can specify +:success+ to indicate 200-299, +:redirect+ to indicate 300-399, +:missing+ to indicate 404, or +:error+ to match the 500-599 range|
|+assert_redirected_to(options = {}, message=nil)+ |Assert that the redirection options passed in match those of the redirect called in the latest action. This match can be partial, such that +assert_redirected_to(:controller => "weblog")+ will also match the redirection of +redirect_to(:controller => "weblog", :action => "show")+ and so on.|
|+assert_template(expected = nil, message=nil)+ |Asserts that the request was rendered with the appropriate template file.|
@@ -524,6 +524,44 @@ You also have access to three instance variables in your functional tests:
* +@request+ - The request
* +@response+ - The response
+h4. Testing Templates and Layouts
+
+If you want to make sure that the response rendered the correct template and layout, you can use the +assert_template+
+method:
+
+<ruby>
+test "index should render correct template and layout" do
+ get :index
+ assert_template :index
+ assert_template :layout => "layouts/application"
+end
+</ruby>
+
+Note that you cannot test for template and layout at the same time, with one call to +assert_template+ method.
+Also, for the +layout+ test, you can give a regular expression instead of a string, but using the string, makes
+things clearer. On the other hand, you have to include the "layouts" directory name even if you save your layout
+file in this standard layout directory. Hence,
+
+<ruby>
+assert_template :layout => "application"
+</ruby>
+
+will not work.
+
+If your view renders any partial, when asserting for the layout, you have to assert for the partial at the same time.
+Otherwise, assertion will fail.
+
+Hence:
+
+<ruby>
+test "new should render correct layout" do
+ get :new
+ assert_template :layout => "layouts/application", :partial => "_form"
+end
+</ruby>
+
+is the correct way to assert for the layout when the view renders a partial with name +_form+. Omitting the +:partial+ key in your +assert_template+ call will complain.
+
h4. A Fuller Functional Test Example
Here's another example that uses +flash+, +assert_redirected_to+, and +assert_difference+:
diff --git a/guides/w3c_validator.rb b/guides/w3c_validator.rb
index f1fe1e0f33..84f34f9293 100644
--- a/guides/w3c_validator.rb
+++ b/guides/w3c_validator.rb
@@ -76,7 +76,7 @@ module RailsGuides
error_summary += "\n #{name}"
error_detail += "\n\n #{name} has #{errors.size} validation error(s):\n"
errors.each do |error|
- error_detail += "\n "+error.to_s.gsub("\n", "")
+ error_detail += "\n "+error.to_s.delete("\n")
end
end