编辑1:这与CanCan gem有关。
这是一个nested_attributes问题。在单一表单上,用户可以创建一个帐户,一个用户帐户(作为'所有者')和一个团队---所有这些都链接到该帐户。 该表单适用于所有者的嵌套属性,但是一旦我添加了Team嵌套属性,我得到一个ActiveModel :: ForbiddenAttributesError。 我已经研究过嵌套模型的构建方法,我认为我的帐户控制器中的语法是正确的 - 请注意has_one和has_many之间的区别。 我真的碰壁了...... 谢谢你的帮助。
我的模特是:
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
则可行。
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
在我的团队控制器中,我有:
private
def team_params
params.require(:team).permit(:name, :active, :account_id)
end
在我的用户控制器中,我有:
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
我的表格很长,所以这只是一段摘录:
<%= 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' %>
完整错误消息的开头:
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:这是我的能力.rb:
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
答案 0 :(得分:2)
在您的fields_for for team中:
<%= f.fields_for :teams do |t| %>
显然Rails没有为参数生成 teams_attributes ,只是团队。由于您没有将团队列入白名单,因此会出现此错误。
答案 1 :(得分:0)
您在AccountController中的account_params方法缺少您尝试通过它的一些参数。至少,:name
,team: [:name]
,:subdomain
和commit
强大的参数是一个非常主要的混乱来源,所以让我试着解释实际发生了什么,希望它能帮助你解决自己的问题,这不是关于ForbiddenAttributesError,而是关于不了解strong_params
根据用户输入创建对象时,可以限制模型级别或控制器级别的访问。在Rails 3中,这是在模型级别,使用attr_accessible,但是有一个very notable failure,其中有人正确地猜到他们已经完全打开了分配管理员权限的权限。在Rails 4中,整个架构被更改为强制在控制器级别进行授权。这种变化就是strong_params所做的。
现在,在每个控制器中,您需要手动将允许的内容列入白名单。您可以使用在account_params中使用的require
和permit
方法执行此操作。您可能已经在教程和示例代码中注意到每个控制器都在执行mymodel_params
之类的操作。然后,在#create
和#update
方法中,您总是有MyModel.new(mymodel_params)
和@mymodel.update_attributes(mymodel_params)
这样的行。
这是理解strong_params
的关键这里发生的事情是:
mymodel_params
中,您要写下要列入白名单的参数列表。所以,写下所有内容,问题是你试图建立一个记录而不告诉Rails这一切都没关系。您可以在错误消息中看到:它写出了您传递的参数列表,从account
开始,然后是owner_attributes
的散列,其中包含team
。将其与您的account_params进行比较,您可以看到那里缺少一堆属性,结构已关闭。
tl; dr Tiago说 - 你的表格结构错误。