CSC/ECE 517 Fall 2012/ch1b 1w64 nn: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
Line 7: Line 7:


==Adding a new controller action to Rails application==
==Adding a new controller action to Rails application==
* Create route in config/routes.rb if needed. Make sure that there is a route that is going to eventually route action, if not create one in routes.rb.  
In Rails controller forms the logical center of the application. Controller is essentially a Ruby class is inherited from ActionController super class. To create a controller, these steps must be followed.
* Add the action method in the appropriate app/controllers/*_controller.rb. You have to add the actual code in other words, the method in the appropriate controller file that will do whatever that action is.
* Add the action method in the appropriate app/controllers/*_controller.rb. This method will have the actual code to do whatever the action is meant to do. For example,
* Ensure there is something for the action to render in app/views/model/action.html.haml. You have to assure that there is something to the action can render what its all done. Every trip through the controller has to end with returning something and will see that although the most common thing is returning a view whose name matches the controller action, we can also return other things.
<pre>
class PostsController < ApplicationController
  def new
  end
end
</pre>
Here the new function creates an instance of Posts controller
* Create a route in config/routes.rb. When the application receives a request from the user, it is this route that determines the appropriate controller and action to run. Example of a route in routes.rb
<pre>
match 'posts/new' => 'posts#new'
</pre>
* Ensure there is something for the action to render in app/views/model/action.html.erb. Every trip through the controller has to end with returning something to the view. Even if there is no explicit render at the end of controller, by default, the Rails looks for that particular action in the app/view/model. For example, the controller shown below has an index method as follows:
<pre>
class PostsController < ApplicationController
  def index
    @posts = Post.all
  end
end
</pre>
The view for this controller will be found in app/view/post/index.html.erb. It is shown below as follows:
<pre>
<h1>Listing Posts</h1>
<table>
  <tr>
    <th>Title</th>
    <th>Description</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>
<% @posts.each do |post| %>
  <tr>
    <td><%= post.title %></td>
    <td><%= post.description %></td>
    <td><%= link_to 'Show', post %></td>
    <td><%= link_to 'Edit', edit_post_path(book) %></td>
    <td><%= link_to 'Remove', post, :confirm => 'Are you sure?', :method => :delete %></td>
  </tr>
<% end %>
</table>
<br />
<%= link_to 'New post', new_post_path %>
</pre>


==MVC responsibilities==
==MVC responsibilities==

Revision as of 23:39, 2 October 2012

SaaS - 3.12 Controller and views

Coursera is a technology company that provides free online education by making videos. SaaS is one such video series made by University of California, Berkley.

Introduction

This article focuses on the concepts and usage of controllers and views in Rails application which is available as one of the SaaS video lectures. It covers the general information about adding a controller to Rails application.

Adding a new controller action to Rails application

In Rails controller forms the logical center of the application. Controller is essentially a Ruby class is inherited from ActionController super class. To create a controller, these steps must be followed.

  • Add the action method in the appropriate app/controllers/*_controller.rb. This method will have the actual code to do whatever the action is meant to do. For example,
class PostsController < ApplicationController
  def new
  end
end

Here the new function creates an instance of Posts controller

  • Create a route in config/routes.rb. When the application receives a request from the user, it is this route that determines the appropriate controller and action to run. Example of a route in routes.rb
match 'posts/new' => 'posts#new'
  • Ensure there is something for the action to render in app/views/model/action.html.erb. Every trip through the controller has to end with returning something to the view. Even if there is no explicit render at the end of controller, by default, the Rails looks for that particular action in the app/view/model. For example, the controller shown below has an index method as follows:
class PostsController < ApplicationController
  def index
    @posts = Post.all
  end
end

The view for this controller will be found in app/view/post/index.html.erb. It is shown below as follows:

<h1>Listing Posts</h1>
 
<table>
  <tr>
    <th>Title</th>
    <th>Description</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>
 
<% @posts.each do |post| %>
  <tr>
    <td><%= post.title %></td>
    <td><%= post.description %></td>
    <td><%= link_to 'Show', post %></td>
    <td><%= link_to 'Edit', edit_post_path(book) %></td>
    <td><%= link_to 'Remove', post, :confirm => 'Are you sure?', :method => :delete %></td>
  </tr>
<% end %>
</table>
 
<br />
 
<%= link_to 'New post', new_post_path %>

MVC responsibilities

  • Model: methods to get/manipulate data. Different methods are provided by active record to do that.
Movie.where(...), Movie.find(...)
  • Controller: In REST applications, the controller acts as a middle man to synchronize the communication between model and view. It is responsible for receiving request from the user, getting data from the model and making it available to the view for displaying data to the user. Controllers are also responsible for routing the requests to internal actions. This is done with the help of Helper methods.
def show
  @movie = Movie.find(params[:id])
end

params which is the parameter from the request that work hopefully parsed out for us by the routing subsystem. Let us assume that it is going to contain the id of the movie that we want to find beacause then we can just call movie.find. This is unsafe because in a real application because if params[:id] happens to be a non-existing thing, we will get an error. So in practice, we either use find by id or use exceptions. The instance variables in the controller are going to be available to the view

  • View: display data, allow user interaction. In this example Show is going to display the details of a movie (description, rating). To select the view for rendering step, the default action the rails will take is, it will try to find a view whose directory name matches the name of the class and finally matches the name of the action.

URI helpers

Once the user is satisfied looking at page, what does he do? There is no place to click. Also how exactly does the user get to this page?

Helper method URI returned RESTful route Action
movies_path /movies GET /movies index
movies_path /movies POST /movies create
new_movie_path /movies/new GET /movies/new new
edit_movie_path(m) /movies/1/edit GET /movies/:id/edit edit
movie_path(m) /movies/1 GET /movies/:id show
movie_path(m) /movies/1 PUT /movies/:id update
movie_path(m) /movies/1 DELETE /movies/:id destroy

Just like the routing subsystem allows us to map http methods and URI's to different control actions, the same routing subsystem also sets up these helpful methods that will generate the routes in the context of the page. Example when we are looking at the list of all movies index.index.html.haml, somewhere on that page there will be a link whose argument is movie_path with an argument.

link_to movie_path(3)

movie_path is the helper that set up and gives back a route to the show action for that movie id. So when the user clicks on it, the URI that is going to be generated is going to be movie/:id with a GET method because its a link. This is how it looks in the actual html.

<a href="/movies/3">...</a>

From here, once the URI is hit, that is going to get looked up in the routing subsystem. /movies/something matches the show action of the movies controller and it will take the wild card thing :id and puts that in params[:id]

GET /movies/:id
{:action=>"show", :controller=>"movies"}
params[:id]

With that appropriate controller action is called

def show
  @movie = Movie.find(params[:id])
end

Here the controller action can reasonably expect to find that params[:id] will be whatever this route said that it should match.

What else can we do?

We can let the user return a list of all movies. We can use RESTful URI helpers. Here it is the index action. movies_path with no arguments links to the index action. The line to add on show template is

link_to 'Back to List', movies_path

Back to List is the text that is click-able and movies_path is a method call. As the app gets more complicate, these mechanism scale very nicely

References

  1. https://www.youtube.com/watch?v=zy7P0E9gs-E
  2. http://en.wikipedia.org/wiki/Representational_state_transfer