Microblog App 3 - Users resource 2020
users table:
users | |
id | integer |
name | string |
string |
Now that we've completed a quick overview of the Users resource (Microblog II), let's examine one particular part of it in the context of the Model-View-Controller (MVC) pattern introduced:
- The browser issues a request for the /users URL.
- Rails routes /users to the index action in the Users controller.
- The index action asks the User model to retrieve all users (User.all).
- The User model pulls all the users from the database.
- The User model returns the list of users to the controller.
- The controller captures the users in the @users variable, which is passed to the index view.
- The view uses embedded Ruby to render the page as HTML.
- The controller passes the HTML back to the browser.
The user makes a request by putting a URL into the address bar. The request hits the Rails router. Then, the router dispatches the request to the proper controller action based on the URL.
The routes for users resource is defined in config/routes.rb:
Rails.application.routes.draw do resources :users ... end
The code in app/controllers/users_controller.rb creates the mapping of user URLs to controller actions for the Users resource. The code sets up the table of URL/action pairs:
URL | Action | Purpose |
---|---|---|
/users | index | page to list all users |
/users/1 | show | page to show user with id 1 |
/users/new | new | page to make a new user |
/users/1/edit | edit | page to edit user with id 1 |
class UsersController < ApplicationController before_action :set_user, only: [:show, :edit, :update, :destroy] # GET /users # GET /users.json def index @users = User.all end # GET /users/1 # GET /users/1.json def show end # GET /users/new def new @user = User.new end # GET /users/1/edit def edit end # POST /users # POST /users.json def create @user = User.new(user_params) respond_to do |format| if @user.save format.html { redirect_to @user, notice: 'User was successfully created.' } format.json { render :show, status: :created, location: @user } else format.html { render :new } format.json { render json: @user.errors, status: :unprocessable_entity } end end end # PATCH/PUT /users/1 # PATCH/PUT /users/1.json def update respond_to do |format| if @user.update(user_params) format.html { redirect_to @user, notice: 'User was successfully updated.' } format.json { render :show, status: :ok, location: @user } else format.html { render :edit } format.json { render json: @user.errors, status: :unprocessable_entity } end end end # DELETE /users/1 # DELETE /users/1.json def destroy @user.destroy respond_to do |format| format.html { redirect_to users_url, notice: 'User was successfully destroyed.' } format.json { head :no_content } end end private # Use callbacks to share common setup or constraints between actions. def set_user @user = User.find(params[:id]) end # Never trust parameters from the scary internet, only allow the white list through. def user_params params.require(:user).permit(:name, :email) end end
Note the line class UsersController < ApplicationController. It's the Ruby's way of doing inheritance.
The table below shows the full suite of controller actions RESTful routes provided by the Users resource:
HTTP request | URL | Action | Purpose |
---|---|---|---|
GET | /users | index | page to list all users |
GET | /users/1 | show | page to show user with id 1 |
GET | /users/new | new | page to make a new user |
POST | /users | create | create a new user |
GET | /users/1/edit | edit | page to edit user with id 1 |
PATCH | /users/1 | update | update user with id 1 |
DELETE | /users/1 | destroy | delete user with id 1 |
To see the relationship between the Users controller and the User model, we may want to focus on a simplified version of the index action for microblog_app.
Here is the simplified code:
class UsersController < ApplicationController ... def index @users = User.all end ... end
This index action has the line @users = User.all (Step 3 in the diagram above). It asks the User model to retrieve a list of all the users from the database, and then places them in the variable @users.
The User model looks like this (app/models/user.rb):
class User < ActiveRecord::Base end
Even though it looks plain, actually it comes with various functionalities thanks to inheritance.
By using the Rails library called Active Record, the code arranges for User.all to return all the users.
Once the @users variable is defined by the controller's index action, then the controller calls the view shown below (app/views/users/index.html.erb):
<h1>Listing users</h1> <table> <thead> <tr> <th>Name</th> <th>Email</th> <th colspan="3"></th> </tr> </thead> <tbody> <% @users.each do |user| %> <tr> <td><%= user.name %></td> <td><%= user.email %></td> <td><%= link_to 'Show', user %></td> <td><%= link_to 'Edit', edit_user_path(user) %></td> <td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td> </tr> <% end %> </tbody> </table> <br> <%= link_to 'New User', new_user_path %>
The index.html.erb view (the code above) iterates through the @users list and outputs a line of HTML for each one.
The view converts its contents to HTML, which is then returned by the controller to the browser for display.
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization