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

This commit is contained in:
Vijay Dev 2012-04-25 18:33:36 +05:30
commit 4a3ce153f1
20 changed files with 242 additions and 44 deletions

@ -64,6 +64,9 @@ module DateHelper
# distance_of_time_in_words(to_time, from_time, true) # => about 6 years
# distance_of_time_in_words(Time.now, Time.now) # => less than a minute
#
# distance_of_time_in_words(70) # => 1 minute
# distance_of_time_in_words(60*60) # => about 1 hour
#
def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false, options = {})
from_time = from_time.to_time if from_time.respond_to?(:to_time)
to_time = to_time.to_time if to_time.respond_to?(:to_time)

@ -902,7 +902,7 @@ def text_area(object_name, method, options = {})
# # Let's say that @post.validated? is 1:
# check_box("post", "validated")
# # => <input name="post[validated]" type="hidden" value="0" />
# # <input type="checkbox" id="post_validated" name="post[validated]" value="1" />
# # <input checked="checked" type="checkbox" id="post_validated" name="post[validated]" value="1" />
#
# # Let's say that @puppy.gooddog is "no":
# check_box("puppy", "gooddog", {}, "yes", "no")

@ -26,7 +26,7 @@ to integrate with Action Pack out of the box: <tt>ActiveModel::Model</tt>.
person = Person.new(:name => 'bob', :age => '18')
person.name # => 'bob'
person.age # => 18
person.valid? # => false
person.valid? # => true
It includes model name introspections, conversions, translations and
validations, resulting in a class suitable to be used with Action Pack.
@ -116,9 +116,6 @@ behavior out of the box:
person.errors.full_messages
# => ["Name can not be nil"]
person.errors.full_messages
# => ["Name can not be nil"]
{Learn more}[link:classes/ActiveModel/Errors.html]
* Model name introspection

@ -58,7 +58,8 @@ def authenticate(unencrypted_password)
BCrypt::Password.new(password_digest) == unencrypted_password && self
end
# Encrypts the password into the password_digest attribute.
# Encrypts the password into the password_digest attribute, only if the
# new password is not blank.
def password=(unencrypted_password)
unless unencrypted_password.blank?
@password = unencrypted_password

@ -26,17 +26,18 @@ module ActiveModel
# person.serializable_hash # => {"name"=>"Bob"}
#
# You need to declare an attributes hash which contains the attributes
# you want to serialize. When called, serializable hash will use
# you want to serialize. Attributes must be strings, not symbols.
# When called, serializable hash will use
# instance methods that match the name of the attributes hash's keys.
# In order to override this behavior, take a look at the private
# method read_attribute_for_serialization.
# method +read_attribute_for_serialization+.
#
# Most of the time though, you will want to include the JSON or XML
# serializations. Both of these modules automatically include the
# ActiveModel::Serialization module, so there is no need to explicitly
# +ActiveModel::Serialization+ module, so there is no need to explicitly
# include it.
#
# So a minimal implementation including XML and JSON would be:
# A minimal implementation including XML and JSON would be:
#
# class Person
# include ActiveModel::Serializers::JSON
@ -63,7 +64,12 @@ module ActiveModel
# person.to_json # => "{\"name\":\"Bob\"}"
# person.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<serial-person...
#
# Valid options are <tt>:only</tt>, <tt>:except</tt> and <tt>:methods</tt> .
# Valid options are <tt>:only</tt>, <tt>:except</tt>, <tt>:methods</tt> and <tt>include</tt>.
# The following are all valid examples:
#
# person.serializable_hash(:only => 'name')
# person.serializable_hash(:include => :address)
# person.serializable_hash(:include => { :address => { :only => 'city' }})
module Serialization
def serializable_hash(options = nil)
options ||= {}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@ -21,4 +21,18 @@ def create
render 'new'
end
end
def edit
@post = Post.find(params[:id])
end
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
end

@ -1,4 +1,4 @@
<%= form_for :post, :url => { :action => :create } do |f| %>
<%= 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>

@ -2,5 +2,4 @@
<%= render 'form' %>
<%= link_to 'Show', @post %> |
<%= link_to 'Back', posts_path %>
<%= link_to 'Back', :action => :index %>

@ -7,6 +7,7 @@
<th>Title</th>
<th>Text</th>
<th></th>
<th></th>
</tr>
<% @posts.each do |post| %>
@ -14,6 +15,7 @@
<td><%= post.title %></td>
<td><%= post.text %></td>
<td><%= link_to 'Show', :action => :show, :id => post.id %>
<td><%= link_to 'Edit', :action => :edit, :id => post.id %>
</tr>
<% end %>
</table>

@ -9,3 +9,4 @@
</p>
<%= link_to 'Back', :action => :index %>
| <%= link_to 'Edit', :action => :edit, :id => @post.id %>

@ -7,6 +7,8 @@
get "posts/new"
post "posts/create"
get "posts/:id" => "posts#show"
get "posts/:id/edit" => "posts#edit"
put "posts/:id/update" => "posts#update"
# The priority is based upon order of creation:
# first created -> highest priority.

@ -388,6 +388,8 @@ The field name can also be a string:
Client.where('locked' => true)
</ruby>
NOTE: The values cannot be symbols. For example, you cannot do +Client.where(:status => :active)+.
h5(#hash-range_conditions). Range Conditions
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.

@ -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.

@ -516,7 +516,7 @@ end
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 our reference to the post object. We do this because Rails will pass all instance
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
@ -577,8 +577,8 @@ end
h4. Adding links
You can now create, show, and list posts. But it's difficult to navigate
through pages, so let's add some 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:
@ -619,19 +619,7 @@ Let's add links to the other views as well.
# app/views/posts/new.html.erb
<%= form_for :post do |f| %>
<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 %>
@ -657,11 +645,9 @@ 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.
and restart the web server when a change is made.
Congratulations, you're riding the rails! Now its time to see how it all works.
h4. The Model
h4. Adding Some Validation
The model file, +app/models/post.rb+ is about as simple as it can get:
@ -676,8 +662,6 @@ 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:
@ -730,7 +714,7 @@ something went wrong. To do that, you'll modify
+app/views/posts/index.html.erb+ to check for error messages:
<erb>
<%= form_for :post do |f| %>
<%= form_for :post, :url => { :action => :create } do |f| %>
<% if @post.errors.any? %>
<div id="errorExplanation">
<h2><%= pluralize(@post.errors.count, "error") %> prohibited
@ -780,6 +764,172 @@ 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/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 red 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.
h4. Using the Console
To see your validations in action, you can use the console. The console is a

@ -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 %>

@ -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

@ -56,7 +56,7 @@ def test_routes_should_not_be_namespaced
run_generator
assert_file "config/routes.rb", /get "account\/foo"/, /get "account\/bar"/
end
#
def test_invokes_default_template_engine_even_with_no_action
run_generator ["account"]
assert_file "app/views/test_app/account"