Creating a new Rails project
Create two models (Parent & Child)
Review un-nested routes
Adding model relationships
Nesting the routes
Reviewing changes to routes
Adding test data via Rails console
Adding a private controller method to load the Parent object for each method
At this point, each controller and view for the Child class model needs to be adjusted (links, redirection, form, etc)
Method: children#index
Method: children#new
Method: children#create
Method: children#show
Method: children#edit
Method: children#update
Method: children#destroy
At this point, the default scaffolding's links and redirection have been updated to work with the nested routes.
$ mkdir family
# create rvm gemset
$ echo "rvm use --create ruby-1.9.2@family"> family/.rvmrc
$ cd family
# install rails
$ gem install rails
# create new rails project
$ rails new.# version control
$ git init
$ git add .
$ git commit -am "new rails project"
Create two models (Parent & Child)
# Parent model
$ rails generate scaffold Parent name:string
$ git add .
$ git commit -am "rails generate scaffold Parent name:string"# Child model
$ rails generate scaffold Child name:string parent_id:integer
$ git add .
$ git commit -am "rails generate scaffold Child name:string parent_id:integer"# Create db (defaults to SQLite3)
$ rake db:migrate
# version control
$ git add db/schema.rb
$ git commit db/schema.rb -m "created database schema"
Review un-nested routes
$ rake routes
children GET /children(.:format) children#index
POST /children(.:format) children#create
new_child GET /children/new(.:format) children#new
edit_child GET /children/:id/edit(.:format) children#edit
child GET /children/:id(.:format) children#show
PUT /children/:id(.:format) children#update
DELETE /children/:id(.:format) children#destroy
parents GET /parents(.:format) parents#index
POST /parents(.:format) parents#create
new_parent GET /parents/new(.:format) parents#new
edit_parent GET /parents/:id/edit(.:format) parents#edit
parent GET /parents/:id(.:format) parents#show
PUT /parents/:id(.:format) parents#update
DELETE /parents/:id(.:format) parents#destroy
Adding model relationships
# file: app/models/parent.rbclassParent<ActiveRecord::Base
attr_accessible :name
has_many :children
end# file: app/models/child.rbclassChild<ActiveRecord::Base
attr_accessible :name,:parent_id
belongs_to :parent
end# version control
$ git commit app/models -m "added relationships to models"
Nesting the routes
# file: config/routes.rb- resources :children
- resources :parents
+ resources :parents do+ resources :children
+end# version control
$ git commit -m config/routes.rb "nested resources in routes file"
Reviewing changes to routes
$ rake routes
parent_children GET /parents/:parent_id/children(.:format) children#index
POST /parents/:parent_id/children(.:format) children#create
new_parent_child GET /parents/:parent_id/children/new(.:format) children#new
edit_parent_child GET /parents/:parent_id/children/:id/edit(.:format) children#edit
parent_child GET /parents/:parent_id/children/:id(.:format) children#show
PUT /parents/:parent_id/children/:id(.:format) children#update
DELETE /parents/:parent_id/children/:id(.:format) children#destroy
parents GET /parents(.:format) parents#index
POST /parents(.:format) parents#create
new_parent GET /parents/new(.:format) parents#new
edit_parent GET /parents/:id/edit(.:format) parents#edit
parent GET /parents/:id(.:format) parents#show
PUT /parents/:id(.:format) parents#update
DELETE /parents/:id(.:format) parents#destroy
Adding test data via Rails console
$ rails c
> dad =Parent.new(:name =>'Paul')=>#<Parent id: nil, name: "Paul", created_at: nil, updated_at: nil> > dad.save
(0.1ms)begin transaction
SQL (20.0ms) INSERT INTO "parents"("created_at","name","updated_at") VALUES (?,?,?)[["created_at",Fri,06Apr201216:13:17 UTC +00:00],["name","Paul"],["updated_at",Fri,06Apr201216:13:17 UTC +00:00]](2.4ms) commit transaction
=>true> son = dad.children.new(:name =>'Eric')=>#<Child id: nil, name: "Eric", parent_id: 1, created_at: nil, updated_at: nil> > daughter = dad.children.new(:name =>'Mara')=>#<Child id: nil, name: "Mara", parent_id: 1, created_at: nil, updated_at: nil> >exit
Adding a private controller method to load the Parent object for each method
# file: app/controllers/children_controller.rb@@-1,4+1,7@@classChildrenController<ApplicationController++ before_filter :load_parent
+# GET /children# GET /children.jsondef index
@@-80,4+83,11@@classChildrenController<ApplicationController
format.json { head :no_content }endend++private++def load_parent
+@parent=Parent.find(params[:parent_id])+end+end
At this point, each controller and view for the Child class model needs to be adjusted (links, redirection, form, etc)
Method: children#index
# file: app/controllers/children_controller.rbdef index
-@children=Child.all
+@children=@parent.children.all
# file: app/views/children/index.html.erb-<td><%= link_to 'Show', child %></td>-<td><%= link_to 'Edit', edit_child_path(child)%></td>-<td><%= link_to 'Destroy', child, confirm:'Are you sure?', method::delete%></td>+<td><%= link_to 'Show', parent_child_path(@parent, child)%></td>+<td><%= link_to 'Edit', edit_parent_child_path(@parent, child)%></td>+<td><%= link_to 'Destroy',[@parent, child], confirm:'Are you sure?', method::delete%></td>-<%= link_to 'New Child', new_child_path %>+<%= link_to 'New Child', new_parent_child_path(@parent)%>
Method: children#new
# file: app/controllers/children_controller.rbdefnew-@child=Child.new+@child=@parent.children.new
# file: app/views/children/_form.html.erb-<%= form_for(@child)do|f|%>+<%= form_for([@parent,@child])do|f|%>
# file: app/views/children/new.html.erb-<%= link_to 'Back', children_path %>+<%= link_to 'Back', parent_children_path(@parent)%>
Method: children#create
# file: app/controllers/children_controller.rbdef create
-@child=Child.new(params[:child])+@child=@parent.children.new(params[:child])
respond_to do|format|if@child.save
- format.html { redirect_to @child, notice:'Child was successfully created.'}+ format.html { redirect_to [@parent,@child], notice:'Child was successfully created.'}
Method: children#show
# file: app/controllers/children_controller.rbdef show
-@child=Child.find(params[:id])+@child=@parent.children.find(params[:id])
# file: app/views/children/show.html.erb-<%= link_to 'Edit', edit_child_path(@child)%>|-<%= link_to 'Back', children_path %>+<%= link_to 'Edit', edit_parent_child_path(@parent,@child)%>|+<%= link_to 'Back', parent_children_path(@parent)%>
Method: children#edit
# file: app/controllers/children_controller.rbdef edit
-@child=Child.find(params[:id])+@child=@parent.children.find(params[:id])
# file: app/views/children/edit.html.erb-<%= link_to 'Show',@child%>|-<%= link_to 'Back', children_path %>+<%= link_to 'Show', parent_child_path(@parent,@child)%>|+<%= link_to 'Back', parent_children_path(@parent)%>
Method: children#update
# file: app/controllers/children_controller.rbdef update
-@child=Child.find(params[:id])+@child=@parent.children.find(params[:id])
respond_to do|format|if@child.update_attributes(params[:child])- format.html { redirect_to @child, notice:'Child was successfully updated.'}+ format.html { redirect_to [@parent,@child], notice:'Child was successfully updated.'}
Method: children#destroy
# file: app/controllers/children_controller.rbdef destroy
-@child=Child.find(params[:id])+@child=@parent.children.find(params[:id])@child.destroy
respond_to do|format|- format.html { redirect_to children_url }+ format.html { redirect_to parent_children_path(@parent)}
At this point, the default scaffolding's links and redirection have been updated to work with the nested routes.