Почему я получаю ActiveRecord :: AssociationTypeMismatch при передаче объекта User в модель уведомлений? - PullRequest
0 голосов
/ 04 февраля 2019

Когда я передаю объект комментария с параметрами в объект Notification.create (), я получаю ActiveRecord :: AssociationTypeMismatch для пользователя.Это говорит о том, что я передал экземпляр Integer (который, возможно, является идентификатором пользователя) вместо самого объекта User.Я не знаю, как мне подойти к получению объекта пользователя из объекта комментария и передаче его в столбец получателя.Я использую камень под названием acts_as_commentable_with_threading .Как передать правильный экземпляр объекта User в Уведомление?

Я попытался получить пользователя, используя цепочку комментариев через comment.commentable.user.Который вернул целевого пользователя.Но по какой-то причине он заявляет, что я не могу использовать объект, так как это тип Integer, а не User.Ниже приведена ошибка.

Comment Load (1.0ms)  SELECT  "comments".* FROM "comments" WHERE "comments"."id" = $1 LIMIT $2 FOR UPDATE  [["id", 16], ["LIMIT", 1]]
  Comment Create (2.0ms)  INSERT INTO "comments" ("commentable_id", "commentable_type", "body", "user_id", "lft", "rgt", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id"  [["commentable_id", 3], ["commentable_type", "Post"], ["body", "Damn"], ["user_id", 2], ["lft", 21], ["rgt", 22], ["created_at", "2019-02-04 18:23:47.285528"], ["updated_at", "2019-02-04 18:23:47.285528"]]
   (1.0ms)  COMMIT
Redirected to http://127.0.0.1:3000/posts/qQ7JeRcQxGXg
  User Load (1.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 3], ["LIMIT", 1]]
Completed 500 Internal Server Error in 6196ms (ActiveRecord: 1466.1ms)



ActiveRecord::AssociationTypeMismatch (User(#211252000) expected, got 2 which is an instance of Integer(#3523260)):

app/controllers/comments_controller.rb:17:in `create'
Processing by ExceptionHandler::ExceptionsController#show as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"KnLViXrCG/67gbUFTQjFMq6eIt7AKvjG4dRgD0JSoPOCOfHqU0n0lVB9l3+lyAc0B+G3mgZ6dv8cG0v9LTvPuw==", "comment"=>{"commentable_id"=>"3", "commentable_type"=>"Post", "body"=>"Damn"}, "commit"=>"Comment"}
Completed 500 Internal Server Error in 285ms (ActiveRecord: 0.0ms)

comments_controller.rb

class CommentsController < ApplicationController
  before_action :authenticate_user!

  def create
    commentable = commentable_type.constantize.find(commentable_id)
    @comment = Comment.build_from(commentable, current_user.id, body)

    respond_to do |format|
      if @comment.save
        make_child_comment
        format.html {redirect_back(fallback_location: post_path(@comment))}
        format.js
      else
        format.html {render :action => :new}
      end
    end
    Notification.create(recipient: @comment.commentable.user, actor: current_user.id, action: "commented on your Post", notifiable: @comment.commentable.id, content: @comment.body.truncate(50).to_s)
#GenericCommentNotificationJob.perform_later(@comment.commentable.user, current_user.id, @comment, body)
  end

  def destroy
    @comment = Comment.find_by_id params[:id]

    respond_to do |format|
      if @comment.destroy
        format.html {redirect_to @comment.commentable}
      else
        format.html {redirect_to @comment.commentable, notice: t('error')}
      end
    end
  end

  private

  def comment_params
    params.require(:comment).permit(:body, :commentable_id, :commentable_type, :comment_id)
  end

  def commentable_type
    comment_params[:commentable_type]
  end

  def commentable_id
    comment_params[:commentable_id]
  end

  def comment_id
    comment_params[:comment_id]
  end

  def body
    comment_params[:body]
  end

  def make_child_comment
    return "" if comment_id.blank?

    parent_comment = Comment.find(comment_id)
    @comment.move_to_child_of(parent_comment)
  end
end

схема комментариев

  create_table "comments", force: :cascade do |t|
    t.integer "commentable_id"
    t.string "commentable_type"
    t.string "title"
    t.text "body"
    t.string "subject"
    t.integer "user_id", null: false
    t.integer "parent_id"
    t.integer "lft"
    t.integer "rgt"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.bigint "post_id"
    t.index ["post_id"], name: "index_comments_on_post_id"
    t.index ["commentable_id", "commentable_type"], name: "index_comments_on_commentable_id_and_commentable_type"
    t.index ["user_id"], name: "index_comments_on_user_id"
  end

comment.rb

class Comment < ActiveRecord::Base
  acts_as_nested_set :scope => [:commentable_id, :commentable_type]
  validates :body, :presence => true
  validates :user, :presence => true

  # NOTE: install the acts_as_votable plugin if you
  # want user to like on the quality of comments.
  acts_as_votable

  belongs_to :commentable, :polymorphic => true

  # NOTE: Comments belong to a user
  belongs_to :user

  # Helper class method that allows you to build a comments
  # by passing a commentable object, a user_id, and comments text
  # example in readme
  def self.build_from(obj, user_id, comment)
    new \
      :commentable => obj,
      :body => comment,
      :user_id => user_id
  end

  #helper method to check if a comments has children
  def has_children?
    self.children.any?
  end

  # Helper class method to lookup all comments assigned
  # to all commentable types for a given user.
  scope :find_comments_by_user, lambda {|user|
    where(:user_id => user.id).order('created_at DESC')
  }

  # Helper class method to look up all comments for
  # commentable class name and commentable id.
  scope :find_comments_for_commentable, lambda {|commentable_str, commentable_id|
    where(:commentable_type => commentable_str.to_s, :commentable_id => commentable_id).order('created_at DESC')
  }

  # Helper class method to look up a commentable object
  # given the commentable class name and id
  def self.find_commentable(commentable_str, commentable_id)
    commentable_str.constantize.find(commentable_id)
  end
end

messages.rb

class Notification < ApplicationRecord
  belongs_to :recipient, class_name: "User"
  belongs_to :actor, class_name: "User"
  belongs_to :notifiable, polymorphic: true
  scope :unread, -> {where(read_at: nil)}
end

схема уведомлений

  create_table "notifications", force: :cascade do |t|
    t.integer "recipient_id"
    t.integer "actor_id"
    t.datetime "read_at"
    t.string "action"
    t.integer "notifiable_id"
    t.string "notifiable_type"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "content"
  end

Фактические результаты : Когда пользователь пытается создать комментарий, уведомление не может создать себя из-за активного несоответствия типов записей для пользовательского объекта.

Ожидаемые результаты: пользователь создает комментарий, а затем уведомление создается после успешной фиксации комментария.

1 Ответ

0 голосов
/ 04 февраля 2019

Использование

Notification.create(recipient: @comment.commentable.user, actor_id: current_user.id, action: "commented on your Career Insight", notifiable: @comment.user, content: @comment.body.truncate(50).to_s)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...