ActiveModel :: ForbiddenAttributesError + cancan + rails 4 +带有作用域控制器的模型

时间:2013-10-09 13:16:57

标签: ruby-on-rails-4 cancan activemodel

我使用带有rails 4.0.0的cancan(1.6.10)。我有一个名为'App'(没有作用域)的模型和一个控制器Admin :: AppsController(它的作用域。即app / controllers / admin / apps_controller)。

控制器代码为

class Admin::AppsController < ApplicationController
  before_filter :authenticate_user!
  load_and_authorize_resource class: App

  def index
  end

  #CRUD methods and some other custom methods
  ...

  private

  def app_params
    params.require(:app).permit(:name, :description, :author, :url_path, :validated, :active, :version)
  end
end

当我尝试创建“应用”时遇到错误。

ActiveModel::ForbiddenAttributesError - ActiveModel::ForbiddenAttributesError:
activemodel (4.0.0) lib/active_model/forbidden_attributes_protection.rb:21:in `sanitize_for_mass_assignment'

我添加了

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

https://github.com/ryanb/cancan/issues/835#issuecomment-18663815中指定但仍然出现上述错误。

3 个答案:

答案 0 :(得分:8)

使用名称空间。请尝试将您的代码更改为以下代码。在@JiriKolarik建议他的解决方案使用名称空间后,我遇到了同样的问题。我希望它有所帮助。

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

答案 1 :(得分:3)

如果您使用此工作流程

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

那么你的params方法看起来应该是这样的

  def admin_app_params
    params.require(:admin_app).permit(:name, :description, :author, :url_path, :validated, :active, :version)
  end

之所以如此,是因为表单生成器(form_form,simple_form)使用namespace_resource生成参数

因此,如果您有Blog :: Post,表单生成器将创建这样的参数

{ "blog_post"=>{"title"=>"Post"}, "commit"=>"Create", "action"=>"create", "controller"=>"blog/posts", "locale"=>"en"}

这就是滤镜工作之前的方法:

before_filter do
  resource = controller_path.singularize.gsub('/', '_').to_sym # => 'blog/posts' => 'blog/post' => 'blog_post' => :blog_post
  method = "#{resource}_params" # => 'blog_post_params'
  params[resource] &&= send(method) if respond_to?(method, true) # => params[:blog_post]
end

如果您需要阅读:来自params的blog_post,上面的解决方案将无效。如果您需要阅读:来自params的帖子,那么如果您的控制器将是博客/帖子

,则此解决方案将无效

答案 2 :(得分:2)

cancan只能用于强参数。虽然有一个新的 cancancan ,它可以很好地运行而无需更改任何代码。