在使用Devise获取关联记录的属性创建用户时创建关联记录

时间:2016-07-10 09:30:06

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

我有一个用户模型,通过模型成员资格,它有很多组织:

class User < ActiveRecord::Base
  has_many :memberships
  has_many :organizations, through: :memberships
end

class Membership < ActiveRecord::Base
  belongs_to :user
  belongs_to :organization
end

class Organization < ActiveRecord::Base
  has_many :memberships
  has_many :users, through: :memberships
end

在注册过程中,我想询问我的组织名称,因此,我的表单如下所示:

= simple_for_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
  = devise_error_messages!
  = f.simple_fields_for :memberships do |fm|
    = fm.input :kind, as: :hidden, input_html: {value: Membership::OWNER}
    = fm.simple_fields_for :organization do |fo|
      = fo.input :name, required: false, label: "Organization"
  = f.input :name
  = f.input :email
  = f.input :password
  = f.input :password_confirmation

我的自定义Devise注册控制器中的自定义强params定义如下所示:

def configure_sign_up_params
  devise_parameter_sanitizer.permit(:sign_up) do |u|
    u.permit(:email, 
             :password, 
             :password_confirmation, 
             memberships: {organizations: [:name]})
  end
end

当我提交表单时,我收到此错误:

Membership(#70355446274100) expected, got Array(#70355394078720)

在Devise上创建控制器动作。参数如下所示:

{"utf8"=>"✓",
 "authenticity_token"=>"...",
 "user"=>
   {"memberships"=>
     {"kind"=>"owner",
      "organizations"=>{"name"=>"Organization name"}},
   "name"=>"User's Name",
   "email"=>"email@address.com",
   "password"=>"[FILTERED]",
   "password_confirmation"=>"[FILTERED]"},
 "commit"=>"Sign up"}

如果我添加

accepts_nested_attributes_for :memberships 
accepts_nested_attributes_for :organizations

到用户模型或添加:

accepts_nested_attributes_for :memberships

到用户模型和

accepts_nested_attributes_for :organizations
对于成员模型,成员和组织简单地消失了表单,它们不会被呈现。即使我的新注册控制器操作如下所示:

def new
  super
  resource.memberships.build.build_organization
end

我也试着用这个来定义我的强力参数:

def configure_sign_up_params
  devise_parameter_sanitizer.permit(:sign_up) do |u|
    u.permit(:email,
             :password,
             :password_confirmation,
             memberships_attributes: [:id, organization_attributess: [:id, :name]])
  end
end

并且(显然)没有出现HTML输入字段。

我错过了什么?我怎样才能做到这一点?

关于这个问题是Expected ProductField, got array issue的重复,在这个问题或答案的任何地方都没有涉及的形式问题,我在这里讨论。

1 个答案:

答案 0 :(得分:1)

我认为你在各种地方犯了几个错误。请使用下面的更正替换您的代码(所以不要错过单数/复数个案)。不幸的是,我无法真正测试我的代码,但我认为它非常接近您的需求。

class User < ActiveRecord::Base
  has_many :memberships
  has_many :organizations, through: :memberships

  accepts_nested_attributes_for :memberships
end

class Membership < ActiveRecord::Base
  belongs_to :user
  belongs_to :organization

  accepts_nested_attributes_for :organization
end

class Organization < ActiveRecord::Base
  has_many :memberships
  has_many :users, through: :memberships
end


= simple_for_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
  = devise_error_messages!
  = f.simple_fields_for :memberships do |fm|
    = fm.input :kind, as: :hidden, input_html: {value: Membership::OWNER}
    = fm.simple_fields_for :organization do |fo|
      = fo.input :name, required: false, label: "Organization"
  = f.input :name
  = f.input :email
  = f.input :password
  = f.input :password_confirmation


def configure_sign_up_params
  devise_parameter_sanitizer.permit(:sign_up) do |u|
    u.permit(:email, 
             :password, 
             :password_confirmation, 
             memberships_attributes: [:id, organization_attributes: [:id, :name]])
  end
end

以下是我处理您的观点的方式(而不是在新操作中构建您的资源)。您可以在新操作中移除您的建筑物并尝试以下视图:

= simple_for_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
  = devise_error_messages!
  = f.object.memberships.build if f.object.memberships.empty?
  = f.simple_fields_for :memberships do |fm|
    = fm.input :kind, as: :hidden, input_html: {value: Membership::OWNER}
    = fm.object.build_organization unless fm.object.organization
    = fm.simple_fields_for :organization do |fo|
      = fo.input :name, required: false, label: "Organization"
  = f.input :name
  = f.input :email
  = f.input :password
  = f.input :password_confirmation
相关问题