Rails x Ajax에서 '즐겨찾기'를 켜고 끌 수 있는 목록 만들기

16115 단어 아약스Railsdevise

소개


  • 이런 느낌의 Ajax로 「즐겨찾기」의 온 오프 할 수 있는 (이어서 카운트도) 리스트를 만듭니다.
  • Devise 를 사용해 로그인하고 있는 상태를 상정하고 있으므로, Devise를 어느 정도 아는 사람용입니다.



  • 이번에 사용할 라이브러리


  • Devise(로그인 처리)
  • Toastr.JS(통지 메시지)
  • CounterCulture(즐겨찾기 카운트)
  • FontAwesomeRails (무료 아이콘)
  • Devise와 CounterCulture, FontAwesomeRails는 Gem이므로 README를 따르십시오.
  • Toastr만은 스스로 JS와 CSS 파일을 다운로드해 와, vendor/assets/toastr 디렉토리 아래에 배치합시다. 파이프라인에서 설정을 잊지 마세요.

  • 필요한 예비 지식


  • Rails의 Ajax 통신.
  • BootStrap4 (뷰의 정형에 사용하고 있을 뿐이므로, 상세하지 않아도 된다)
  • Slim 템플릿 (2와 유사)
  • 사용되는 라이브러리에 대한 지식

  • 환경


    $ ruby -v
    ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux]
    
    $ rails -v
    Rails 5.2.1
    

    구현



    모델


  • 이번에는 UserDog , Like 모델을 사용합니다.
  • User 모델은 Devise 로 작성합니다.
  • Like 를 중간 테이블로 하고, UserDog 를 다대다의 연관짓는 것으로, 좋아 관계를 구축합니다.
  • seed-fu 라든가를 사용해, DB에 미리 페이지네이션용의 인스턴스를 만들어 둡시다.
  • # マイグレーション
    class CreateDogs < ActiveRecord::Migration[5.2]
      def change
        create_table :dogs do |t|
          t.string :name, null: false, default: ''
          t.integer :receive_likes_count, null: false, default: 0
        end
      end
    end
    
    class CreateLikes < ActiveRecord::Migration[5.2]
      def change
        create_table :likes do |t|
          t.references :user
          t.references :dog
        end
      end
    end
    
    class User < ApplicationRecord
      has_many :likes, dependent: :destroy
    end
    
    class Dog < ApplicationRecord
      has_many :receive_likes, dependent: :destroy, class_name: 'Like'
    
      # 特定のユーザーからお気に入りされているか
      def liked_by?(user)
        user.likes.exists?(dog_id: id)
      end
    
      # Ajax実行時に、DOMエレメントを特定するID
      def id_attribute
        "dog-#{id}"
      end
    end
    
    class Like < ApplicationRecord
      belongs_to :user
      belongs_to :dog
      # counter culture設定
      counter_culture :dog, column_name: 'receive_likes_count'
    end
    

    컨트롤러


  • 이번 페이지를 sample#index 액션으로 합니다.
  • "좋아요"해도 순서가 표시의 순서가 바뀌지 않도록, order 를 설정해 둡니다.
  • class SampleController < ApplicationController
      def index
        @dogs = Dog.all.order(created_at: :asc) 
      end
    end
    
  • 또한 Ajax에서 좋아하는 음을 켜고 끄기위한 API 컨트롤러 api/like_controller.rb를 추가하십시오.
  • 이 컨트롤러 호출시에 실행되는 JS 파일은 나중에 기재합니다.
  • class Api::LikeController < ApplicationController
      before_action :setup_dog!
      before_action :setup_like!
    
      def create
        @like.save
      end
    
      def destroy
        @like.destroy
      end
    
      private
    
      def setup_dog!
        @dog = Dog.find(params[:dog_id])
      end
    
      def setup_like!
        # create時はまだ存在していないのでinitializeされ、
        # destroy時は既に存在しているのでfindされる。
        @like = current_user
                  .likes
                  .find_or_initialize_by(dog_id: @dog.id)
      end
    end
    
  • 라우팅은 이런 느낌.
  • namespace :api do
      post 'like/:dog_id' => 'like#create', as: :like
      delete 'like/:dog_id' => 'like#destroy', as: :unlike
    end
    

    도우미


  • 좋아요를 켜고 끄는 버튼을 렌더링하는 도우미 메서드를 만듭니다.
  • 이를 통해 로그인 중인 사용자가 특정 Dog 모델을 즐겨찾는지 여부를 결정하여 아이콘과 링크를 분리할 수 있습니다.
  • module MyHelper
      def toggle_like_button(dog)
        # ログインしていない場合
        return fa_icon 'heart-o', text: dog.receive_likes_count if current_user.blank?
    
        liked = dog.liked_by?(current_user)
        icon = fa_icon (liked ? 'heart' : 'heart-o'), text: dog.reload.receive_likes_count
        if liked
          # お気に入りを外すボタン
          link_to icon, api_unlike_path(dog_id: dog.id), remote: true, method: :delete
        else
          # お気に入りするボタン
          link_to icon, api_like_path(dog_id: dog.id), remote: true, method: :post
        end
      end
    end
    

    보기


  • 이번 준비하는 뷰는, 대원의 페이지용과, Dog의 파셜 뷰의 2개입니다.
  • # ページ
    app/views/sample/
    ├── _dog.html.slim
    └── index.html.slim
    
    / index.html.slim
    .container.my-5
      .row
        .col-md-6.offset-md-3
          #project-list(style='overflow-y: scroll; height: 80vh;')
            = render @dogs
    
    / _dog.html.slim
    .card.card-body.mb-3(id="#{dog.id_attribute}")
      / この.like要素をAjaxで書き換える
      .like
        = toggle_like_button(dog)
      h3.card-title = dog.name
    

    JS 파일


  • 마지막으로 like 컨트롤러 호출시에 호출되는 JS 파일을 추가합니다.
  • app/views/api/like/
    ├── create.js.erb
    └── destroy.js.erb
    
    // create.js.erb
    
    // toastrの通知処理
    toastr.success("<%= "#{@like.dog.name}をお気に入りに追加しました" %>")
    // 特定のLIKEボタンのDOMを入れ替える。
    $("<%= "##{@dog.id_attribute} .like" %>").html("<%= j toggle_like_badge(@dog) %>") 
    
    // destroy.js.erb
    
    toastr.error("<%= "#{@dog.name}をお気に入りから削除しました" %>")
    $("<%= "##{@dog.id_attribute} .like" %>").html("<%= j toggle_like_badge(@dog) %>")
    

    결론


  • 걸어서 했지만, 일단 이것으로 「즐겨찾기 처리」를 할 수 있게 되었습니다.
  • 여러가지 편리한 라이브러리가 있으면 좋네요.
  • 좋은 웹페이지 즐겨찾기