RoR多嵌套与多态关联+设计

时间:2015-03-05 00:19:26

标签: ruby-on-rails devise nested-attributes polymorphic-associations

在使用设计提交注册表单时,我希望保存不同模型的多态关联。即: 用户 公司+ ContactInfo 员工+ ContactInfo

我知道不建议使用嵌套表格,但实现这一目标的最佳方法是什么?

由于

模型:

class User < ActiveRecord::Base
  belongs_to :company
  accepts_nested_attributes_for :company
end

class Company < ActiveRecord::Base
  has_many :employees
  has_one :contact_info, as: :contactable
  accepts_nested_attributes_for :contact_info
end

class Employee < ActiveRecord::Base
  belongs_to :company
  has_one :contact_info, as: :contactable
  accepts_nested_attributes_for :contact_info
end

class ContactInfo < ActiveRecord::Base
  belongs_to :imageable, polymorphic: true
end

迁移:

class CreateCompanies < ActiveRecord::Migration
  def change
    create_table :companies do |t|
      t.string :name
      t.references :contact_info, index: true
      t.string :website
      t.timestamps null: false
    end
    add_foreign_key :companies, :contact_infos
  end
end

class CreateEmployees < ActiveRecord::Migration
  def change
    create_table :employees do |t|
      t.string :first_name
      t.string :last_name
      t.references :company, index: true
      t.references :contact_info, index: true
      t.string :job_title
      t.timestamps null: false
    end
    add_foreign_key :employees, :contact_infos
  end
end

class CreateContactInfos < ActiveRecord::Migration
  def change
    create_table :contact_infos do |t|
      t.string :email
      t.string :phone
      t.string :mobile
      t.string :contactable_type
      t.integer :contactable_id

      t.timestamps null: false
    end
  end
end

注册管理员:

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up).push(:name, :email, :password, company_attributes: [ :id, :name, :website, :company_type, :number_of_employees, contact_info_attributes: [ :id, :email, :phone, :mobile]])
  end

设计新注册:

<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :role => 'form'}) do |f| %>
    <%= devise_error_messages! %>

    <%= hidden_field_tag 'plan', params[:plan] %>

    <% resource.build_company %>
    <%= f.fields_for :company do |f| %>
      <%= render "companies/fields", f: f %>
    <% end %>

    <% resource.company.build_contact_info %>
    <%= f.fields_for :contact_info do |f| %>
      <%= render "contact_infos/fields", f: f %>
    <% end %>

    <div class="form-group">
      <%= f.label :name %>
      <%= f.text_field :name, :autofocus => true, class: 'form-control' %>
    </div>
    <div class="form-group">
      <%= f.label :email %>
      <%= f.email_field :email, class: 'form-control' %>
    </div>
    <div class="form-group">
      <%= f.label :password %>
      <%= f.password_field :password, class: 'form-control' %>
    </div>
    <div class="form-group">
      <%= f.label :password_confirmation %>
      <%= f.password_field :password_confirmation, class: 'form-control' %>
    </div>
     <%= f.submit 'Sign up', :class => 'button right' %>
<% end %>

控制台:

  Parameters: {"utf8"=>"✓", "authenticity_token"=>"Nb6Na8P93s1dYvlDIQuiG11IoDeSzSylH4BCN8Tm7ipxCsbsdiWjDx5tJpijwldkjK4pPfjuwROnEvybYS7UIQ==", "plan"=>"free", "user"=>{"company_attributes"=>{"name"=>"Company Name", "website"=>"company website", "company_type"=>"company type", "number_of_employees"=>"121"}, "contact_info"=>{"email"=>"company@email.com", "phone"=>"1234", "mobile"=>"1234"}, "name"=>"user_name", "email"=>"user_email@email.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign up"}
Unpermitted parameter: contact_info

只有用户和公司的参数保存得很好。我试图让devise_parameter_sanitizer首先在公司中嵌套contact_info,而不是尝试与员工一样,知道我做错了什么或任何提示,如果我在正确的轨道上?

谢谢!

更新

但是,如果我将contact_info表单字段嵌套在公司表单字段中,则允许使用contact_info参数:

<% resource.build_company %>
<%= f.fields_for :company do |f| %>
  <%= render "companies/fields", f: f %>
  <% resource.company.build_contact_info %>
  <%= f.fields_for :contact_info do |cf| %>
    <%= render "contact_infos/fields", f: cf %>
  <% end %>
<% end %>

问题是,这是一种好的做法吗?

1 个答案:

答案 0 :(得分:0)

这是 guess - 但您公司的contact_info并未嵌套在公司部分内。试试这样的事情(注意,未经测试,可能是马车)

<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :role => 'form'}) do |f| %>
<%= devise_error_messages! %>

<%= hidden_field_tag 'plan', params[:plan] %>

<% resource.build_company %>
<%= f.fields_for :company do |f| %>
  <%= render "companies/fields", f: f %>

  <%# this is now nested inside the company-fields %>
  <% resource.company.build_contact_info %>
  <%= f.fields_for :contact_info do |f| %>
    <%= render "contact_infos/fields", f: f %>
  <% end %>

<% end %>

<div class="form-group">
  <%= f.label :name %>
  <%= f.text_field :name, :autofocus => true, class: 'form-control' %>
</div>
<div class="form-group">
  <%= f.label :email %>
  <%= f.email_field :email, class: 'form-control' %>
</div>
<div class="form-group">
  <%= f.label :password %>
  <%= f.password_field :password, class: 'form-control' %>
</div>
<div class="form-group">
  <%= f.label :password_confirmation %>
  <%= f.password_field :password_confirmation, class: 'form-control' %>
</div>
 <%= f.submit 'Sign up', :class => 'button right' %>