当我将带有参数的注释对象传递给Notification.create()对象时,我收到了User的ActiveRecord :: AssociationTypeMismatch。它说明我传入了一个Integer实例(可能是用户ID),而不是User对象本身。我不知道应该如何从注释对象中获取用户对象并将其传递给收件人列。我正在使用名为 acts_as_commentable_with_threading 的gem。如何将User对象的正确实例传递给Notification?
我试图通过链接comment.commentable.user来检索用户。其中返回了目标用户。但是,由于某种原因,它表明我不能使用该对象,因为它是整数类型而不是用户类型。错误如下。
ArrayIndexOutOfBoundsException
comments_controller.rb
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)
评论架构
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
comment.rb
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
notification.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
通知架构
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
实际结果:当用户尝试创建评论时,由于用户对象的活动记录类型不匹配,因此通知无法自行创建。
预期结果:用户创建评论,然后在成功提交评论后创建通知。
答案 0 :(得分:1)
使用
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)