[RUBY] [Rails] [jQuery] Asynchronous like function implementation using remote: true and js.erb

Overview

While creating a bulletin board site in a Rails project, I had the opportunity to implement an asynchronous like feature using remote: true and the js.erb file. I will leave the procedure here as a memorandum.

Premise

Rails 5.0

It is assumed that create favorites_table and define model association have already been done.

association: users - has_many :posts, has_many :favorites posts - belongs_to :user, has_many :favorites favorites - belongs_to :user, belongs_to :post

jQuery preparation

Prepare to use jQuery within Rails. First, introduce the gem.

Gemfile


gem 'jquery-rails'

** bundle install ** in the terminal. Then add the description to ʻapplication.js`.

application.js


# Rails5.Before 1
//= require jquery
//= require jquery-ujs

#Version is Rails 5.For 1 or later
//= require jquery
//= require rails-ujs

This time, I'm using Rails 5.0, so please require jquery_ujs. In this case, make sure to ** require jquery first **.

By the way, rails-ujs is installed by default from Rails 5.1, so you can just require it in application.js.

Routing settings

Describe the routing using the post method for the create action and the delete method for the destroy action. You can specify the Prefix name by writing as: as an option.

routes.rb


  post '/favorite/:post_id' => 'favorites#create', as: 'like'
  delete '/favorite/:post_id' => 'favorites#destroy', as: 'unlike'

Creating favorites_controller

Define like create and destroy.

app/controllers/favorites_controller.rb


class FavoritesController < ApplicationController
   before_action :set_post
   
   def create
      @favorite = Favorite.create(user_id: current_user.id, post_id: @post.id)
   end
   
   def destroy
      @favorite = Favorite.find_by(user_id: current_user.id, post_id: @post.id)
      @favorite.destroy
   end
   
   private
   
   def set_post
      @post = Post.find(params[:post_id])
   end
end

Create view with partial template

It is made into a partial template so that it can be reused easily.

erb:app/views/users/show.html.erb


<%= render 'posts/posts', posts: @posts %>

erb:app/views/users/_post.html.erb


<% posts.each do |post| %>


  <div id="favorite-<%= post.id %>">
    <%= render partial: "favorites/favorite", locals: { post: post } %>
  </div>
<% end %>

In order to fire an event with js, specify a selector with id or class, but this time it is necessary to include the id of that post in the id to determine which post you like. You can specify an id like id = "post-1" by writing as above.

erb:app/views/favorites/_favorite.html.erb


<% if Favorite.find_by(user_id: current_user.id, post_id: post.id) %>
  <%= link_to "How nice", unlike_path(post.id), method: :delete, remote: true,  class: "btn btn-default" %>
<% else %>
  <%= link_to "How nice", like_path(post.id), method: :post, remote: true, class: "btn btn-success" %>
<% end %>
<%= post.favorites.length %>

Add remote: true to the link_to of the like button. This description allows you to call the js.erb file where you would normally call the html.erb file that corresponds to the action called link_to. Therefore, communication will be performed asynchronously without page transition. Finally, the number of likes is displayed as <% = post.favorites.length%>.

js.erb file creation

First, create a js.erb file corresponding to each action of create and destroy. app/views/favorites/create.js.erb app/views/favorites/destroy.js.erb

erb:app/views/favorites/create.js.erb


$("#favorite-<%= @post.id %>").html("<%= j(render partial: 'favorites/favorite', locals: { post: @post }) %>");

erb:app/views/favorites/destroy.js.erb


$("#favorite-<%= @post.id %>").html("<%= j(render partial: 'favorites/favorite', locals: { post: @post }) %>");

First, specify the selector, but specify it so that it corresponds to ʻid = "favorite- <% = post.id%>`. Then, use jQuery's html () method to replace the html of the specified selector.

What to replace " <% = j (render partial:'favorites / favorite', locals: {post: @post})%> " part calls _favorite.html.erb of the partial template. (J in front of render is an alias for escape_javascript, a method that escapes line breaks and parentheses.)

This completes the implementation of the asynchronous like function!

スクリーンショット 2020-09-24 21.26.48.png

スクリーンショット 2020-09-24 21.31.17.png

Finally

Thank you for reading this far. If you find any mistakes, please let us know.

Recommended Posts

[Rails] [jQuery] Asynchronous like function implementation using remote: true and js.erb
[Rails] Asynchronous implementation of like function
[Rails 6] Like function (synchronous → asynchronous) implementation
[Rails] Implementation of like function
[Rails] I tried to implement "Like function" using rails and js
[Rails] About implementation of like function
[Rails] Implementation of tag function using acts-as-taggable-on and tag input completion function using tag-it
[Ruby on rails] Implementation of like function
[Rails] Implementation of search function using gem's ransack
[Rails 6] Implementation of inquiry function using Action Mailer
[Rails] Implementation of image enlargement function using lightbox2
[Nuxt / Rails] POST implementation using axios and devise_token_auth
[Rails, JavaScript] Implemented like function (synchronous / asynchronous communication)
[Rails] Implementation of drag and drop function (with effect)
Rails CRUD function implementation ② (edited and detailed this time)
[Rails] Implementation of multi-layer category function using ancestry "Preparation"
[Rails] Implementation of multi-layer category function using ancestry "seed"
Rails search function implementation
Try to implement tagging function using rails and js
[Rails] Implementation of multi-layer category function using ancestry "Editing form"
[Rails] Implementation of multi-layer category function using ancestry "Creation form"
Rails sorting function implementation (displayed in order of number of like)
[Rails] Implementation of tagging function using intermediate table (without Gem)
Rails fuzzy search function implementation
Search function using [rails] ransack
[Rails 6] Implementation of search function
[Rails] Implementation of category function
Login function implementation with rails
Ajax bookmark function using Rails
[Rails] Implementation of tutorial function
[Rails 6] Pagination function implementation (kaminari)
[Rails] Implementation of new registration function in wizard format using devise
[Implementation procedure] Create a user authentication function using sorcery in Rails
[Rails] Implementation of coupon function (with automatic deletion function using batch processing)
[Rails] Implementation of CSV import function
[Rails] Implementation of image preview function
User evaluation using the like function
[Rails] Tag management function (using acts-as-taggable-on)
[Rails] Implementation of user withdrawal function
[Rails] Implementation of CSV export function
[Rails] gem ancestry category function implementation
[Ruby on Rails] Comment function implementation
[Rails] Comment function implementation procedure memo
Implementation of like function in Java
[Rails] I will explain the implementation procedure of the follow function using form_with.