首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有嵌套属性的构建上的ForbiddenAttributesError

具有嵌套属性的构建上的ForbiddenAttributesError
EN

Stack Overflow用户
提问于 2014-08-06 21:05:40
回答 2查看 1.4K关注 0票数 0

编辑1 :这是与CanCan gem相关的。

这是一个nested_attributes问题。在单个表单上,用户可以创建一个帐户、一个用户帐户(作为“所有者”)和一个团队--所有这些都链接到帐户上。该表单可以很好地处理只有所有者的嵌套属性,但是一旦添加了团队嵌套属性,就会得到一个ActiveModel::ForbiddenAttributesError。我研究了嵌套模型的构建方法,我认为我的语法在我的帐户控制器中是正确的--注意has_one和has_many之间的区别。我真的撞到了墙..。谢谢你的帮助。

我的模特是:

代码语言:javascript
复制
class Account < ActiveRecord::Base
  RESTRICTED_SUBDOMAINS = %w(www)
  has_one :owner, class_name: 'User'
  has_many :teams
  validates :owner, presence: true
  validates :name, presence: true
  accepts_nested_attributes_for :owner, :teams

class Team < ActiveRecord::Base
  acts_as_tenant :account
  has_many :users
  belongs_to :account
  validates_inclusion_of :active, :in => [true, false]
  validates :name, presence: true, allow_nil: false
  validates_uniqueness_to_tenant :name

class User < ActiveRecord::Base
  devise :invitable, :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable 
  acts_as_tenant :account
  belongs_to :team
  validates :lastname, presence: true, allow_nil: false
  validates :firstname, presence: true, allow_nil: false
  validates_uniqueness_to_tenant :email

  def self.current_id
    Thread.current_user[:user_id]
  end

我的账户管理员:

编辑2 :,如果我注释掉load_and_authorize_resource,它就能工作。

代码语言:javascript
复制
class AccountsController < ApplicationController
  skip_before_filter :authenticate_user!, only: [:new, :create]
  #load_and_authorize_resource

  def new
    @account = Account.new
    @account.build_owner
    @account.teams.build
    #@account.teams.build(teams_params)  # tried this
    #@account.teams.build(params[:team])  # tried this
  end

  def create
    @account = Account.new(account_params)
    respond_to do |format|
     if @account.save
       format.html { redirect_to new_user_session_url(subdomain: @account.subdomain) }
     else
       format.html { render action: 'new' }
       format.json { render json: @account.errors, status: :unprocessable_entity }
     end
   end
 end
 Private
  def account_params
    params.require(:account).permit(:subdomain, :name, :logo, :owner_id, :time_zone, :default_language, :publish_to_wall_new_employee, :publish_to_wall_new_document, :publish_to_wall_published_schedule, :publish_to_wall_modified_schedule, teams_attributes: [:id, :name, :account_id], owner_attributes: [:lastname, :firstname, :email, :password, :password_confirmation, :account_id])
    end
 end

在我的团队控制员中,我有:

代码语言:javascript
复制
private
  def team_params
    params.require(:team).permit(:name, :active, :account_id)
  end

在我的用户控制器中,我有:

代码语言:javascript
复制
private
   def user_params
     params.require(:user).permit(:firstname, :lastname, :email, :account_id, :avatar, :role, :street_address, :zip, :city, :phone, :dob, :pob, :citizenship, :team_id, :contract_time)
   end

我的表格很长,所以这只是一个节选:

代码语言:javascript
复制
 <%= form_for @account, html: {id: 'accounts-new-form'} do |f| %>
    <%= f.fields_for :owner do |o| %>
      <%= o.label :firstname, "Your firstname" %>
      <%= o.text_field :firstname, options = {class: "form-control required", rel: "FirstName"} %>
    <% end %>
    <%= f.label :subdomain, "Choose a subdomain" %>
    <%= f.text_field :subdomain, options = {class: "form-control required", rel: "Subdomain"} %>
    <%= f.fields_for :teams do |t| %>
      <%= t.label :name, "Choose a team name" %>
      <%= t.text_field :name, options = {class: "form-control required", rel: "Team"} %>
    <% end %>
<%= f.submit class: 'btn btn-primary' %>

以下是完全错误消息的开头:

代码语言:javascript
复制
Processing by AccountsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"UTdyTCq3hpxR/w23JzJnWYozOLQhxpfOZPLql6b5+m8=", "account"=>{"owner_attributes"=>{"firstname"=>"john", "lastname"=>"Doe", "email"=>"john@test8.com",     "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "name"=>"Test8 Inc", "subdomain"=>"test8", "teams_attributes"=>{"0"=>{"name"=>"Test8-Team-A"}}}, "commit"=>"Create Account"}
  Account Load (0.6ms)  SELECT  "accounts".* FROM "accounts"  WHERE "accounts"."subdomain" IS NULL  ORDER BY "accounts"."id" ASC LIMIT 1
  Account Load (0.4ms)  SELECT  "accounts".* FROM "accounts"  WHERE "accounts"."subdomain" = '' LIMIT 1
Completed 500 Internal Server Error in 10ms

ActiveModel::ForbiddenAttributesError - ActiveModel::ForbiddenAttributesError:
  activemodel (4.1.1) lib/active_model/forbidden_attributes_protection.rb:21:in `sanitize_for_mass_assignment'
  activerecord (4.1.1) lib/active_record/attribute_assignment.rb:24:in `assign_attributes'
  activerecord (4.1.1) lib/active_record/core.rb:452:in `init_attributes'
  activerecord (4.1.1) lib/active_record/core.rb:198:in `initialize'
  activerecord (4.1.1) lib/active_record/inheritance.rb:30:in `new'
  cancan (1.6.10) lib/cancan/controller_resource.rb:85:in `build_resource'
  cancan (1.6.10) lib/cancan/controller_resource.rb:66:in `load_resource_instance'
  cancan (1.6.10) lib/cancan/controller_resource.rb:32:in `load_resource'
  cancan (1.6.10) lib/cancan/controller_resource.rb:25:in `load_and_authorize_resource'
  cancan (1.6.10) lib/cancan/controller_resource.rb:10:in `block in add_before_filter'
  activesupport (4.1.1) lib/active_support/callbacks.rb:440:in `block in make_lambda'
  activesupport (4.1.1) lib/active_support/callbacks.rb:160:in `block in halting'
  activesupport (4.1.1) lib/active_support/callbacks.rb:149:in `block in halting_and_conditional'
  activesupport (4.1.1) lib/active_support/callbacks.rb:166:in `block in halting'
  activesupport (4.1.1) lib/active_support/callbacks.rb:149:in `block in halting_and_conditional'
  activesupport (4.1.1) lib/active_support/callbacks.rb:166:in `block in halting'
  activesupport (4.1.1) lib/active_support/callbacks.rb:166:in `block in halting'
  activesupport (4.1.1) lib/active_support/callbacks.rb:229:in `block in halting'
  activesupport (4.1.1) lib/active_support/callbacks.rb:166:in `block in halting'
  activesupport (4.1.1) lib/active_support/callbacks.rb:86:in `run_callbacks'

编辑3 :这是我的ability.rb:

代码语言:javascript
复制
class Ability
  include CanCan::Ability

  def initialize(user)
     user ||= User.new # guest user (not logged in)
     can :create, Account

     # only owner can read & manage Account details
     can :manage, Account if user.role == "owner"
     cannot :read, Account if user.role == "employee"
     cannot :read, Account if user.role == "manager"

     # owner has full access to User details, manager can create/edit all User details, employee can read/list other User details
     # employee can edit own details except contract information
     can :manage, User if user.role == "owner"
     can :manage, User if user.role == "manager"
     cannot :update, User if user.role == "employee"
     can :update, User, :id => user.id  # a user can only update its own record
     can :avatar, User, :id => user.id  # a user can only edit own photo
     can :address, User, :id => user.id  # a user can only update its own address
     can :view_contract, User, :id => user.id # a user cannot updedit own contract infos
     can :read, User if user.role == "employee"
     can :home, User if user.role == "employee"
  end
end
EN

Stack Overflow用户

发布于 2014-08-06 22:04:43

您的account_params方法在AccountController中丢失了很多试图通过它的参数。至少,:nameteam: [:name]:subdomaincommit

强对撞机是造成混乱的主要原因,所以让我试着解释一下实际发生了什么,希望它能帮助您解决自己的问题,这不是关于ForbiddenAttributesError的,而是关于不理解strong_params的。

当您基于用户输入创建对象时,可以在模型级别或控制器级别限制访问。在Rails 3中,这是在模型级别上使用attr_accessible的,但是其中有一个非常显著的失败,其中有人正确地猜到他们保留了分配管理员权限的权限。在Rails 4中,整个体系结构被更改为在控制器级别强制授权。这一变化正是strong_params所做的。

现在,在每个控制器中,您需要手动地列出允许通过的内容。使用在require中使用的permit和account_params方法就可以做到这一点。您可能在教程和示例代码中注意到,每个控制器都在执行类似于mymodel_params的操作。然后,在#create#update方法中,您总是有一个类似于MyModel.new(mymodel_params)@mymodel.update_attributes(mymodel_params)的行。

这是理解strong_params的关键

这里发生的是:

  1. mymodel_params中,您要写下要白名单的参数列表。
  2. strong_params接受浏览器和白名单中的原始参数哈希,您所说的一切都是安全的。它会向后吐出一个params散列的副本,只使用白色的params。它还特别标记他们说“嘿,伙计们,这很酷,这些是允许的”
  3. 如果您传递的是在params散列中没有被白化的任何内容,并且尝试用它更新或创建一个新记录,它会向您发出抱怨,抛出一个ForbiddenAttributeError,就像这里所做的那样。

因此,在写下所有这些之后,问题在于您正在尝试构建一个记录,而不告诉Rails这一切都是可以的。您可以在错误消息中看到这一点:它写出要传递的参数列表,从account开始,然后是owner_attributes的散列,其中包含team。将其与您的account_params进行比较,您可以看到那里缺少了许多属性,并且结构已经关闭。

tl;博士提戈说--你的表格结构不正确.

票数 0
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25170191

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档