Как ограничить гем act_as_votable только для одной модели в рельсах - PullRequest
0 голосов
/ 29 мая 2018

У меня есть приложение rails, в котором у меня есть две таблицы Posts & Reviews, в Posts я добавил подобную систему, созданную с нуля, но в Reviews я бы хотел использовать гем acts_as_votable .Я добавил драгоценный камень, и все работает нормально, но, поскольку модель пользователя для сообщений и обзоров одинакова, аналогичная система в сообщениях перестала работать, она выдает следующую ошибку:

NoMethodError (undefined method `vote_by' for nil:NilClass):
  app/models/user.rb:64:in `add_like_to'
  app/controllers/api/likes_controller.rb:11:in `create'

Iдумаю, что эта ошибка происходит, потому что я объявил пользователя как избирателя, но в сообщениях, которые не требовались.Можете ли вы сказать мне, если есть какой-либо способ объявить acts_as_voter в user.rb только для одной модели, в моем случае Обзор?

user.rb

class User < ActiveRecord::Base
  acts_as_voter
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :omniauthable, :omniauth_providers => [:facebook, :twitter, :google_oauth2]
  validates :username, presence: true
  validate :avatar_image_size

      has_many :posts, dependent: :destroy
      has_many :quotes, dependent: :destroy
      has_many :responses, dependent: :destroy
      has_many :likes, dependent: :destroy
      has_many :liked_posts, through: :likes, source: :likeable, source_type: "Post"
      has_many :liked_responses, through: :likes, source: :likeable, source_type: "Response"

      has_many :bookmarks, dependent: :destroy
      has_many :bookmarked_posts, through: :bookmarks, source: :bookmarkable, source_type: "Post"
      has_many :bookmarked_responses, through: :bookmarks, source: :bookmarkable, source_type: "Response"

      has_many :notifications, dependent: :destroy, foreign_key: :recipient_id

      after_destroy :clear_notifications
      after_commit :send_welcome_email, on: [:create]

      mount_uploader :avatar, AvatarUploader

      include UserFollowing
      include TagFollowing
      include SearchableUser
      include OmniauthableUser

      extend FriendlyId
      friendly_id :username, use: [ :slugged, :finders ]

      def add_like_to(likeable_obj)
        likes.where(likeable: likeable_obj).first_or_create
      end

      def remove_like_from(likeable_obj)
        likes.where(likeable: likeable_obj).destroy_all
      end

      def liked?(likeable_obj)
        send("liked_#{downcased_class_name(likeable_obj)}_ids").include?(likeable_obj.id)
      end

      def add_bookmark_to(bookmarkable_obj)
        bookmarks.where(bookmarkable: bookmarkable_obj).first_or_create
      end

      def remove_bookmark_from(bookmarkable_obj)
        bookmarks.where(bookmarkable: bookmarkable_obj).destroy_all
      end

      def bookmarked?(bookmarkable_obj)
        send("bookmarked_#{downcased_class_name(bookmarkable_obj)}_ids").include?(bookmarkable_obj.id)
      end

      private

        # Validates the size on an uploaded image.
        def avatar_image_size
          if avatar.size > 5.megabytes
            errors.add(:avatar, "should be less than 5MB")
          end
        end

        # Returns a string of the objects class name downcased.
        def downcased_class_name(obj)
          obj.class.to_s.downcase
        end

        # Clears notifications where deleted user is the actor.
        def clear_notifications
          Notification.where(actor_id: self.id).destroy_all
        end

        def send_welcome_email
          WelcomeEmailJob.perform_later(self.id)
        end
    end

likes_controller.rb

# This controller serves as a parent controller for other likes_controllers. 
# Posts::LikesController for example.
# Child controller that inherit from this LikesController should implement 
# before_action :set_likeable, which sets @likeable.
class API::LikesController < ApplicationController
  before_action :authenticate_user!
  before_action :set_likeable
  skip_before_action :verify_authenticity_token

  def create
    current_user.add_like_to(@likeable)
    notify_author
    render json: { liked: true, count: @likeable.reload.likes.size, type: @likeable.class.to_s, id: @likeable.id }, status: 200
  end

  def destroy
    current_user.remove_like_from(@likeable)

    render json: { liked: false, count: @likeable.reload.likes.size, type: @likeable.class.to_s, id: @likeable.id }, status: 200
  end

  private

    def set_likeable
      raise NotImplementedError, "This #{self.class} cannot respond to 'set_likeable'"
    end

    def notify_author
      unless current_user?(@likeable.user)
        Notification.create(recipient: @likeable.user, actor: current_user, action: "liked your", notifiable: @likeable, is_new: true)
      end
    end
end

1 Ответ

0 голосов
/ 29 мая 2018

В вашей модели User нет вызова vote_by, поэтому я не уверен, как вы можете вставить сообщение об ошибке в ваш вопрос.

В любом случае вам, вероятно, следует реализовать метод set_likeableв вашем контроллере, так что переменная экземпляра @likeable, переданная в качестве параметра в current_user.add_like_to(@likeable), установлена.

Я думаю, что это должно исправить вашу текущую проблему.

...