Rails 5 Basics : Model View Controller
- Learn how the View communicates with the Controller
- Learn how Controller interacts with the Model and how Controller picks the next View to show to the user.
Router knows which controller can handle the incoming request. Controller is like a traffic cop who controls the flow of traffic on busy streets. Controller has the knowledge of which model can get the job done, so it delegates the work to the appropriate model object. Controller also knows which view to display to the user after the incoming request has been processed.
Why MVC architecture? The advantage of MVC is the clean separation of View from the Model and Controller. It allows you to allocate work to teams according to their strengths. The View layer can be developed in parallel by the front-end developers without waiting for the Model and Controller parts to be completed by the back-end developers.
If we agree on the contract between the front-end and back-end by defining the data representation exchanged between the client and server then we can develop in parallel.
Let's modify the existing static page in app/views/welcome/index.html.erb to use a view helper for hyperlink:
<%= link_to 'My Blog', ? %>
<%= should be used whenever you want the generated output to be shown in the browser. If it is not to be shown to the browser and it is only for dynamic embedding of Ruby code then you should use
<% %> tags.
link_to(text, url) method is a view helper that will generate an html hyperlink that users can click to navigate to a web page. In this case we want the user to go to articles controller, index page. Because we want to get all the articles from the database and display them in the app/views/articles/index.html.erb page.
So the question is what should replace the ? in the second parameter to the
link_to view helper? Since we know we need to go to articles controller, index action, let's use the output of rake routes to find the name of the view helper we can use.
Prefix Verb URI Pattern Controller#Action articles GET /articles(.:format) articles#index POST /articles(.:format) articles#create new_article GET /articles/new(.:format) articles#new edit_article GET /articles/:id/edit(.:format) articles#edit article GET /articles/:id(.:format) articles#show PATCH /articles/:id(.:format) articles#update PUT /articles/:id(.:format) articles#update DELETE /articles/:id(.:format) articles#destroy root GET / welcome#index
As you can see from the output, for articles#index the Prefix value is articles. So we can use either
articles_path (relative url, which would be /articles) or
articles_url (absolute url, which would be
Change the link as follows :
<%= link_to 'My Blog', articles_path %>
Go to the home page by going to the
http://localhost:3000 in the browser. What do you see in the home page? You will see the hyper link in the home page.
Right click and do 'View Page Source' in Chrome or 'Show Page Source' in Safari. You will see the hyperlink which is a relative url.
<a href="/articles">My Blog</a>
Change the articles_path to articles_url in the welcome/index.html.erb. Reload the page.
<a href="http://localhost:3000/articles">My Blog</a>
You will see the absolute URL.
Click on the 'My Blog' link.
You will see the above error page with 'uninitialized constant ArticlesController' error.
When you click on that link, you can see from rails server log that the client made a request:
Started GET "/articles" for ::1 at 2015-11-27 11:09:42 -0800 ActionController::RoutingError (uninitialized constant ArticlesController):
GET '/articles' that was recognized by the Rails router and it looked for articles controller. Since we don't have the articles controller, we get the error message for the uninitialized constant. In Ruby, class names are constant.
You can also use HTTP Live Headers Chrome plugin to see the client and server interactions.
Here you see the client-server interaction details. As you see in the above figure, you can learn a lot by looking at the Live HTTP Header details such as Etag which is used for caching by Rails.
Create the articles controller by running the following command in the blog directory:
$rails g controller articles index
Go back to the home page and click on My Blog link. You will see a static page.
We need to replace the static page with the list of articles from the database. Open the articles_controller.rb in the app/controllers directory and change the index method as follows :
def index @articles = Article.all end
Here the @articles is an instance variable of the articles controller class. It is made available to the corresponding view class by Rails. In this case the view is app/views/articles/index.html.erb
The class method
all retrieves all the records from the articles table.
Open the app/views/articles/index.html.erb in your code editor and add the following code:
<h1>Listing Articles</h1> <% @articles.each do |article| %> <%= article.title %> <%= article.description %> <br/> <% end %>
Here we are using the Ruby scriptlet tag
<% %> for looping through all the records in the articles collection and the values of each record is displayed in the browser using
<%= %> tags.
If you make a mistake and use
<%= %> tags instead of Ruby scriptlet tag in app/views/index.html.erb like this:
<%= @articles.each do |article| %>
You will see the objects in the array displayed on the browser. Articles are displayed as objects inside an array.
If you use the Ruby scriptlet tag :
Title : <% article.title %>
instead of the tags used to evaluate expressions and display to the browser then you will not see it in the browser.
Go to the browser and reload the page for
http://localhost:3000/articles. You will see the list of articles now displayed in the browser.
As you can see from the diagram Controller controls the flow of data into and out of the database and also decides which View should be rendered next.
Go to the rails server log terminal, what is the http verb used to make the request for displaying all the articles? What is the resource that was requested?
In this lesson we went from the view (home page) to the controller for articles and to the article model and back to the view (index page for articles). So the MVC components interaction as shown in the diagram:
- View to Controller
- Controller to Model
- Controller to View
The data flow was from the database to the user. In the real world the user data comes from the user so we cannot create them in the rails console or in the database directly. In the next lesson we will see how we can capture data from the view provided by the user and save it in the database.