I tried to make a message function of Rails Tutorial extension (Part 2): Create a screen to display

This is a continuation of the task of creating a message function in Chapter 14 of the Rails Tutorial.

The model was made up to the last time. Make a screen to display.

Designed View specifications to display DM

Create a way to display DM. Read 13.2 "Displaying Microposts" in the tutorial.

Instead of displaying it according to the User's screen like Micropost, we will display it on a separate page. Similar to Twitter.

Make a mockup. Since there are multiple senders, refer to Figure 14.5 as a mockup showing the senders.


DM(3) Image 1 Thomas Hobbes Lorem ipsum sent 1 day ago. Image 2 Sasha Smith Also poor, nasty, sent 2 days ago. Image 3 John Calvin Excepteur sint sent 3 days ago.

Previous 1 2 3 next


Figure DM page mockup

Create a View to display DM

Generate a controller to create a controller and a view.

ubuntu:~/environment/sample_app (create-dm) $ rails generate controller Dms

Make a view. Refer to Listings 13.22 and 13.24.

ruby:app/views/dms/show.html.erb


<% provide(:title, @user.name)%>
<div class="row">
  <div class="col-md-8">
    <% if @user.send_dms.any? %>
      <h3>DMs (<%= @user.sent_dms.count %>)</h3>
      <ol class="dms">
        <li id="dm-<%= dm.id %>">
          <%= link_to gravatar_for(dm.sender, size: 50), dm.sender %>
          <span class="user"><%= link_to dm.sender.name, dm.sender%></span>
          <span class="content"><%= dm.content %></span>
          <span class="timestamp">
            Sent <%= time_ago_in_words(dm.created_at) %> ago.
          </span>
        </li>
      </ol>
    <% end %>  
  </div>
</div>

Create a controller to display DM

Create a controller to display the new DM page. Read "12.1.1 Password Resets Controller" in the tutorial.

config/routes.rb


Rails.application.routes.draw do
  root 'static_pages#home'
  get  '/help',    to: 'static_pages#help'
  get  '/about',   to: 'static_pages#about'
  get  '/contact', to: 'static_pages#contact'
  get  '/signup',  to: 'users#new'
  post '/signup',  to: 'users#create'
  get  '/login',   to: 'sessions#new'
  post '/login',   to: 'sessions#create'
  delete '/logout', to: 'sessions#destroy'
  resources :users do
    member do
      get :following, :followers
    end
  end
    resources :account_activations, only: [:edit]
  resources :password_resets,     only: [:new, :create, :edit, :update]
  resources :microposts,          only: [:create, :destroy]
  resources :relationships,       only: [:create, :destroy]
  resources :dms,                 only: [:new, :create, :index, :destroy]
end
HTTP request URL Action Named route
GET /dms/new new new_dm_path
POST /dms create dms_path
GET /dms index dms_path
DELETE dms/ destroy dm_path

RESTful routing

Read "10.3.1 User List Page" in the tutorial. There was a link added to the list "10.40: Update the link to the user list page". Add in the same way.

ruby:views/layouts/_header.html.erb


                <ul class="dropdown-menu">
                  <li><%= link_to "Profile", current_user %></li>
                  <li><%= link_to "Settings", edit_user_path(current_user) %></li>
                  <li><%= link_to "DM", dms_path %></li>

Display the screen to verify that the link has been added to the menu.

dm1.png

I'll create a test to Redirect if I'm not logged in later.

I noticed that the controller is index, but the view is show. Rename the file. show.html.erb -> index.html.erb

app/controllers/dms_controller.rb


class DmsController < ApplicationController
  def index
  end
end

Display the screen as a trial

Let's display it on the screen with rails server. I got an error. The message is undefined method `name' for nil:NilClass So, where the error occurred <% provide(:title, @user.name)%> is. I think @user is nil. To set @user to the logged-in user, refer to the user's show screen and change it in the same way.

app/controllers/dms_controller.rb


class DmsController < ApplicationController
  def index
      @user = current_user
  end
end

I will display it on the screen. I got an error again.

undefined local variable or method `dm' for #<#<Class:0x00005575f57bf2a8>:0x00005575f57deb58>

Where the error occurred

  <li id="dm-<%= dm.id %>">

is. I think I need to put data in @dms in my controller. Let's see how to display the micropost on the home screen.

With a controller

      @micropost  = current_user.microposts.build
      @feed_items = current_user.feed.paginate(page: params[:page])

And @feed_items with data.

In view

python


  <ol class="microposts">
    <%= render @feed_items%>
  </ol>

And @feed_items are listed by render. I will change it for reference.

app/controllers/dms_controller.rb


  def index
      @user = current_user
      @dms = @user.sent_dms
  end

In Micropost, it seems good to refer to Chapter 13 which makes good use of feed and feed_items. In reading back

render @user

I wasn't sure what that meant, so I'll go back and read it back. To the controller

app/controllers/dms_controller.rb


  def index
      @user = current_user
      @dms = @user.sent_dms.paginate(page: params[:page])
  end

In that case, in view

<span class="user"><%= link_to dm.sender.name, dm.sender%></span>

Think about what to write in.

ruby:app/views/dms/index.html.erb


<% provide(:title, @user.name) %>
<h1>DM</h1>

<% if @user.sent_dms.any? %>
    <h3>DMs (<%= @user.sent_dms.count %>)</h3>
    <ol class= "microposts">
      <%= render @dms %>  
    </ol>
    <%= will_paginate @dms %>
<% end %>  

ruby:app/views/dms/_dm.html.erb


<li id="dm-<%= dm.id %>">
  <%= link_to gravatar_for(dm.sender, size: 50), dm.sender %>
  <span class="user"><%= link_to dm.sender.name, dm.sender%></span>
  <span class="content"><%= dm.content %></span>
  <span class="timestamp">
    Sent <%= time_ago_in_words(dm.created_at) %> ago.
  </span>
</li>

I will try to display the screen with rails server. There is only one page due to the small amount of data. Increase the data to see if pagnate is done. Let's use Faker :: Hipster.sentence to generate test data for content.

db/seeds.rb


# DM
users = User.order(:created_at).take(6)
receiver = users.second
50.times do
  content = Faker::Hipster.sentence
  users.each {|user| user.sent_dms.create!(content: content,
                                           receiver_id: receiver.id) }
end

Let's display the screen.

dm3.png

I noticed that the receiver is not coming out, so I will change it from the sender.

ruby:app/views/dms/_dm.html.erb


<li id="dm-<%= dm.id %>">
  <%= link_to gravatar_for(dm.receiver, size: 50), dm.receiver %>
  <span class="user"><%= link_to dm.receiver.name, dm.receiver%></span>

dm4.png

DM display test creation

Create a test of the screen that displays the DM. Refer to "13.2.3 Testing the micropost on the profile screen" in the tutorial.

test/fixtures/dms.yml


...
<% 30.times do |n| %>
dm_<%= n %>:
  content: <%= Faker::Hipster.sentence %>
  created_at* <%= 42.days.ago %>
  sender: michael
  receiver: archer
<% end %>

test/integration/dms_test.rb


class DmsTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:michael)
  end
  
  test "dm display" do
    log_in_as(@user)
    get dms_path
    assert_template 'dms/index'
    assert_select 'title', full_title(@user.name)
    assert_match @user.sent_dms.count.to_s, response.body
    assert_select 'div.pagination'
    @user.sent_dms.paginate(page: 1).each do |dm| 
      assert_match CGI.escapeHTML(dm.content), response.body
    end
  end

As shown in Listing 13.28, symbols such as "'" were output as special characters, so I searched the net for how to escape and corrected it. https://rakuda3desu.net/rakudas-rails-tutorial14-3/

Creating a controller access control test

Make a test for the controller. Read "13.3.1 Micropost Access Control" in the tutorial.

test/controllers/dms_controller_test.rb


  test "should redirect index when not logged in" do
    get dms_path
    assert_redirected_to login_url
  end  

It's RED. Add access restrictions for the index action to the controller.

app/controllers/dms_controller.rb


class DmsController < ApplicationController
  before_action :logged_in_user, only: [:index]

The test is now GREEN.

Time required

7.0 hours from 11/7 to 11/14.

Recommended Posts

I tried to make a message function of Rails Tutorial extension (Part 2): Create a screen to display
I tried to make a message function of Rails Tutorial extension (Part 1): Create a model
I tried to make a reply function of Rails Tutorial extension (Part 3): Corrected a misunderstanding of specifications
Rails Tutorial Extension: I tried to create an RSS feed function
I made a reply function for the Rails Tutorial extension (Part 1)
I tried to make a group function (bulletin board) with Rails
I made a reply function for Rails Tutorial extension (Part 2): Change model
[Rails] Implementation of multi-layer category function using ancestry "I tried to make a window with Bootstrap 3"
[Rails / JavaScript / Ajax] I tried to create a like function in two ways.
I tried to make a login function in Java
Rails Tutorial Extension: I created a follower notification function
I tried to create a shopping site administrator function / screen with Java and Spring
Tutorial to create a blog with Rails for beginners Part 1
[Rails] I tried to create a mini app with FullCalendar
I tried using Hotwire to make Rails 6.1 scaffold a SPA
Tutorial to create a blog with Rails for beginners Part 2
I tried to make a client of RESAS-API in Java
Tutorial to create a blog with Rails for beginners Part 0
I made a reply function for the Rails Tutorial extension (Part 4): A function that makes the user unique
I tried to implement Ajax processing of like function in Rails
I tried to make the "Select File" button of the sample application created in the Rails tutorial cool
I tried to make a machine learning application with Dash (+ Docker) part2 ~ Basic way of writing Dash ~
I tried to make a parent class of a value object in Ruby
I tried to create a LINE clone app
How to make a follow function in Rails
[First environment construction] I tried to create a Rails 6 + MySQL 8.0 + Docker environment on Windows 10.
I tried to implement a function equivalent to Felica Lite with HCE-F of Android
Rails6 I want to make an array of values with a check box
[Android] I tried to make a material list screen with ListView + Bottom Sheet
I tried to create a Clova skill in Java
I want to define a function in Rails Console
I tried to create a log reproduction script at the time of apt install
[Rails] I want to display the link destination of link_to in a separate tab
I tried to create a java8 development environment with Chocolatey
I want to implement a product information editing function ~ part1 ~
I want to make a specific model of ActiveRecord ReadOnly
[Swift] I tried to implement the function of the vending machine
I tried to make the sample application into a microservice according to the idea of the book "Microservice Architecture".
I want to make a function with kotlin and java!
I want to create a form to select the [Rails] category
A series of steps to create portfolio deliverables with Rails
[Rails 6.0, Docker] I tried to summarize the Docker environment construction and commands necessary to create a portfolio
[Ruby on Rails] Since I finished all Rails Tutorial, I tried to implement an additional "stock function"
[Rails] I tried to implement "Like function" using rails and js
I tried to create a padrino development environment with Docker
I tried to create a simple map app in Android Studio
I want to create a chat screen for the Swift chat app!
I want to add a browsing function with ruby on rails
[Rails 6] How to create a dynamic form input screen using cocoon
I tried to implement the image preview function with Rails / jQuery
I tried to create a Spring MVC development environment on Mac
[Unity] I tried to make a native plug-in UniNWPathMonitor using NWPathMonitor
I tried to build a simple application using Dockder + Rails Scaffold
[Java] I tried to make a maze by the digging method ♪
(Ruby on Rails6) Create a function to edit the posted content
Preparing to create a Rails application
[Rails Tutorial Chapter 5] Create a layout
How to make a splash screen
Using the face detection function of Watson Visual Recognition, I tried to process a whole body image of a person into an image of only the face part
I tried to make a machine learning application with Dash (+ Docker) part1 ~ Environment construction and operation check ~
I tried to make a sample program using the problem of database specialist in Domain Driven Design