【问题标题】:ForbiddenAttributesError for polymorphic model in Rails 4Rails 4中多态模型的ForbiddenAttributesError
【发布时间】:2013-05-08 08:27:10
【问题描述】:

Rails 4 附带 strong_parameters,这是一个很好的补充 - 但我遇到了问题。我有一个多态模型Comment,我无法让控制器接受它需要的参数。这是我的代码(为清楚起见缩短了):

路线:

resources :articles do
  resources :comments
end

型号:

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

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

控制器:

class CommentsController < ApplicationController
  before_action :get_commentable

  def create
    @comment = @commentable.comments.new(comment_params)
    if @comment.save
      redirect_to @commentable, :notice => "Thank you!"
    else
      render :new
    end
  end

private

  def get_commentable
    resource, id = request.path.split("/")[1,2]
    @commentable = resource.singularize.classify.constantize.find(id)
    redirect_to :home unless defined?(@commentable)
  end

  def comment_params
    params.require(:comment).permit(:title, :message)
  end
end

发布的参数(来自文章#show 上的表格):

{"authenticity_token"=>"v70nN8aFpofNw9vbVjhpsm9SwLOwKlOpNOEOTozUwCk=",
"comment"=>{"title"=>"Test","message"=>"Testing"},
"article_id"=>"1"}

在我看来它应该可以工作,但无论我尝试什么我都会得到ActiveModel::ForbiddenAttributesError in CommentsController#create - 即使我尝试了

  def comment_params
    params.permit! 
  end

在控制器中。我的其他(非多态)模型没有这样的问题,这就是为什么我怀疑它与多态性有关。有任何想法吗?

【问题讨论】:

  • 实际上,这似乎是由 CanCan 引起的错误,我用它来进行基于角色的授权 - 禁用它可以创建 cmets。嗯。

标签: parameters ruby-on-rails-4 cancan mass-assignment polymorphism


【解决方案1】:

由于缺乏答案似乎表明我在这里叫错了树。问题不在于strong_parameters,而在于我用于进行基于角色和操作的授权的CanCan gem。显然,这与 CanCan 如何将参数分配给对象有关(CanCan 接管默认的 ActionController 方法) - 请参阅this bug report 中的详细信息,特别是the reply from "rewritten"。简而言之,把它放在我的应用程序控制器中解决了这个问题:

before_filter do
  resource = controller_name.singularize.to_sym
  method = "#{resource}_params"
  params[resource] &&= send(method) if respond_to?(method, true)
end

更新:

正如@scaryguy 所指出的,如果从没有关联模型的控制器调用上述方法,它将失败。解决方案是简单地命名该方法并将其称为 before_filter,同时在那些没有模型的控制器中明确排除它(因此无论如何都不会从 CanCan 的自动能力分配中受益)。我估计是这样的:

before_filter :can_can_can

def can_can_can
  resource = controller_name.singularize.to_sym
  method = "#{resource}_params"
  params[resource] &&= send(method) if respond_to?(method, true)
end

然后在无模型控制器中:

skip_before_filter :can_can_can

【讨论】:

  • 这与我遇到的问题完全相同,并且此解决方案效果很好。我敢打赌,随着时间的推移,会有更多人遇到这个问题。
  • 感谢@Ecnalyr,很高兴听到它对某人有帮助!
  • 是的,它仅在控制器和模型存在并且都正确命名时才有效。当您想在没有模型的情况下使用控制器时,这会破坏事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-07
  • 2013-07-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多