我正在努力实现多态评论(这些几乎可以应用于网站上的任何用户内容,并且不限于 Article 实例。创建评论时,我需要确定它属于哪个 commentable。大部分写作我have found on this subject 建议我在下面的代码中使用 find_commentable 中指定的模式,但这种方法并没有让我觉得非常优雅 - 似乎应该有一种直接的方法来明确指定 commentable 正在创建新注释for,不遍历params集,不进行字符串匹配,有没有更好的方法?

换句话说,在 commentablecomment 关联的上下文中,是否有更好的方法从 commentable Controller 访问 comment 对象?在我们还没有 create 对象可以使用的 @comment 方法中,它是否仍然有效?

我的模型设置如下:

class Comment < ActiveRecord::Base
  belongs_to :commentable, :polymorphic => true
end

class Article < ActiveRecord::Base
  has_many :comments, :as => :commentable, dependent: :destroy
end

class CommentsController < ApplicationController
  def create
    @commentable = find_commentable
    @comment = @commentable.comments.build(comment_params)

    if @comment.save
      redirect_to :back
    else
      render :action => 'new'
    end
  end

  def index
    @commentable = find_commentable
    @comments = @commentable.comments
  end

  private
    def comment_params
      params.require(:comment).permit(:body)
    end

    def find_commentable
      params.each do |name, value|
        if name =~ /(.+)_id$/
          return $1.classify.constantize.find(value)
        end
    end
  end
end

谢谢!

最佳答案

我也在寻找这个问题的答案,并想分享 Launch Academy's Article on Polymorphic Associations,因为我觉得它提供了最简洁的解释。
对于您的应用程序,还有两个附加选项:

1. “Ryan Bates”方法:(当您使用 Rails 的传统 RESTful URL 时)

def find_commentable
    resource, id = request.path.split('/')[1, 2]
    @commentable = resource.singularize.classify.constantize.find(id)
end

2. 嵌套资源:
def find_commentable
    commentable = []
    params.each do |name, value|
      if name =~ /(.+)_id$/
        commentable.push($1.classify.constantize.find(value))
      end
    end
    return commentable[0], commentable[1] if commentable.length > 1
    return commentable[0], nil if commentable.length == 1
    nil
end

3. 单一资源:(您的实现但重复完成)
def find_commentable
  params.each do |name, value|
    if name =~ /(.+)_id$/
      return $1.classify.constantize.find(value)
    end
  end
  nil
end

10-08 06:48