未允许的参数:使用嵌套属性传递用户参数时的用户错误

时间:2014-04-22 20:07:15

标签: ruby-on-rails activerecord ruby-on-rails-4

我有一个表单,用于收集公司信息以及第一个用户(公司管理员)。当我提交表单时,公司属性将保存到数据库中。但是,用户属性不是。我收到错误Unpermitted parameters: user。我无法弄清楚为什么没有创建和保存用户。

我有:

class CompaniesController < ApplicationController

  def new
    @company = Company.new
    @plans = Plan.all
  end

  def create
    @company = Company.new(company_params)

    @user = User.new
    @user.role = "admin"
    @user.save

    if @company.save
      redirect_to @company, notice: 'Company was successfully created.'
    else
     render action: 'new'
    end
  end

  private
    # Never trust parameters from the scary internet, only allow the white list through.
    def company_params
      params.require(:company).permit(:name, :plan_id, users_attributes: [:id, :company_id, :email, :password, :password_confirmation, :first_name, :last_name, :role, :rate])
    end
end

class UsersController < ApplicationController

#  include UsersHelper

  def index
    @users = User.all
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    @user.save
    flash.notice = "User '#{@user.first_name} #{@user.last_name}' was successfully created."
    redirect_to user_path(@user)
  end

  def show
    @user = User.find(params[:id])
  end

  def edit
    @user = User.find(params[:id])
  end

  def update
    @user = User.find(params[:id])
    @user.update(user_params)

    flash.notice = "User '#{@user.first_name}' has been updated."
    redirect_to user_path(@user)
  end

  def destroy
  end

  private
    # Never trust parameters from the scary internet, only allow the white list through.
    def user_params
      params.require(:user).permit(:email, :password, :password_confirmation, :first_name, :last_name, :role, :rate)
    end

end

class Company < ActiveRecord::Base
  has_many :users
  belongs_to :plan
  accepts_nested_attributes_for :users, :allow_destroy => true
end

class User < ActiveRecord::Base

  authenticates_with_sorcery!
  validates_confirmation_of :password, message: "should match confirmation", if: :password
  has_many :jobs
  belongs_to :company

end

<%= form_for(@company) do |f| %>
  <% if @company.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@company.errors.count, "error") %> prohibited this company from being saved:</h2>

      <ul>
      <% @company.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name, :id => "name" %>
  </div>
  <div class="field">
    <%= collection_select( :company, :plan_id, @plans, :id, :name ) %>
  </div>
  <%= f.fields_for :user do |user| %>
  <div class="field">
    <%= user.label :email %><br>
    <%= user.text_field :email %>
  </div>
  <div class="field">
    <%= user.label :password %><br>
    <%= user.password_field :password %>
  </div>
  <div class="field">
    <%= user.label :password_confirmation %><br>
    <%= user.password_field :password_confirmation %>
  </div>
  <div class="field">
    <%= user.label :first_name %><br>
    <%= user.text_field :first_name %>
  </div>
  <div class="field">
    <%= user.label :last_name %><br>
    <%= user.text_field :last_name %>
  </div>
  <div class="field">
    <%= user.label :role %><br>
    <%= user.text_field :role %>
  </div>
    <% end %>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

ActiveRecord::Schema.define(version: 20140421235514) do

  create_table "companies", force: true do |t|
    t.string   "name"
    t.string   "stripe_token"
    t.integer  "plan_id"
    t.integer  "user_id",      limit: 255
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "companies", ["plan_id"], name: "index_companies_on_plan_id"
  add_index "companies", ["user_id"], name: "index_companies_on_user_id"

  create_table "plans", force: true do |t|
    t.string   "stripe_id"
    t.string   "name"
    t.integer  "amount"
    t.string   "interval"
    t.string   "currency"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "users", force: true do |t|
    t.string   "email",                           null: false
    t.string   "crypted_password",                null: false
    t.string   "salt",                            null: false
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "reset_password_token"
    t.datetime "reset_password_token_expires_at"
    t.datetime "reset_password_email_sent_at"
    t.string   "first_name"
    t.string   "last_name"
    t.string   "role"
    t.integer  "rate"
    t.integer  "company_id"
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true
  add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token"

end

2 个答案:

答案 0 :(得分:1)

CompanyUser 1-M关系相关联,即公司has_many:用户

在这种情况下,在您的公司视图中,嵌套表单应为

<%= f.fields_for :users do |user| %>  ## Notice users in plural

而不是

<%= f.fields_for :user do |user| %>

请参阅 One to Many

的嵌套属性示例

目前,fields_for使用单数:user设置不正确,因此在params hash中,您将密钥设为:user,并再次显示警告Unpermitted parameters: user,因为用户属性为没有存储在数据库中。

现在,您已在accepts_nested_attributes_for模型中设置了Company。 Controller期望在params哈希中的密钥users_attributes中的用户属性。

使用复数fields_for参数更改:users将导致在表单提交时在params哈希中创建users_attributes键。

<强>更新

公司拥有众多用户,其1-M关系 只有users表的外键应为company_id。 您需要从user_id表中删除companies

另外,请按以下步骤更新CompaniesController#new操作:

def new 
  @company = Company.new 
  @users = @company.users.build 
  @plans = Plan.all 
end

答案 1 :(得分:0)

强大的params允许看起来很好,但我认为问题是嵌套的形式,你使用错误的关系名称user,而users生成一个标题为user的参数哈希这是不允许的,你应该这样做:

<%= f.fields_for :users do |user| %>
  #rest of the form elements
<% end %>