【问题标题】:Create record using through association and nested_form_for rails使用通过关联和nested_form_for rails 创建记录
【发布时间】:2017-09-26 09:53:11
【问题描述】:

以下是我的模型结构

role.rb 

has_many :user_roles 
has_many :users, through: :user_roles 
has_many :companies, through: :user_roles

user.rb

has_one :user_role, dependent: :destroy
has_one :role, through: :user_role
has_one :company, through: :user_role 

company.rb

has_many :user_roles, dependent: :destroy 
has_many :users, through: :user_roles
has_many :roles, through: :user_roles

user_role.rb

belongs_to :user
belongs_to :role, optional: true
belongs_to :company

我想使用关联和嵌套形式创建记录,现在我可以使用嵌套形式与用户一起创建公司,但我也想为用户创建 user_role。

我已将accepts_nested_attributes_for :users 包含在公司模型中。 并使用fields_for 以公司新形式创建用户。

以下是我的表格

<%= form_for @company, html: { multipart: true } 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 |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field form-group">
    <%= f.label :name %>
    <%= f.text_field :name, class: :"form-control" %>
  </div>

  <div class="field form-group">
    <%= f.label :website %>
    <%= f.text_field :website, class: :"form-control" %>
  </div>

  <div class="field form-group">
    <%= f.label :phone %>
    <%= f.text_field :phone, class: :"form-control" %>
  </div>

  <div class="field form-group">
    <%= f.label :description %>
    <%= f.text_area :description, class: :"form-control" %>
  </div>

  <div class="field form-group">
    <%= f.file_field :company_image %>
  </div>

  <%= f.fields_for :users do |builder| %>
    <%= render "users_fields", :f => builder %>
  <% end %>

  <div class="actions">
    <%= f.submit class: :'btn btn-default' %>
  </div>

<% end %>

目前,创建公司时未创建 user_role。我不确定如何继续。

任何指导将不胜感激。提前致谢。

【问题讨论】:

  • user_role 未创建,因此必须有某种错误消息或未创建它的原因。包括你的控制器代码,包括@company.errors.full_messages 的输出和检查你的参数是如何显示的。也许user_role 不是saving,因为它无效。 user_role 有一个 belongs_to :user 和一个 belongs_to :role, optional: true。将跳过验证 role 是否存在,但您需要有一个有效的 user。如果你给 user_role 一个属于未保存用户的 user_id,验证将失败。
  • 感谢@Fabrizio 的快速回复,我已验证用户。 UserRole 是用户和公司的第三个表。 user_role 的字段是 user_id、role_id 和 company_id。它使用 user_id 和 company_id 创建 user_role,但不将 role_id 包含到 user_role 记录中。请查看强大的参数params.require(:company).permit(:name, :website, :phone, :description, :company_image, users_attributes: [:email, :first_name, :last_name, :phone, :string, :birth_date, :join_date, :gender, :password, :password_confirmation])
  • user_role belongs_to useruser_role.user_id 必须对应于现有 useridusers 中一行的字段 id。如果您尝试保存user_roleuser 尚未保存,您将触发验证错误并且user_role 将不会被保存。在创建user_role之前保存user
  • 您的db 结构错误。 user has_one :rolerole has_many :users。您只需在创建用户时设置user.role_id 字段。无需创建对象,您可以在 seed.rb 文件中创建标准 roles,如果需要,您可以提供单独创建 roles 的功能。当您创建user 时,您只需设置他将拥有的角色,而不是创建对象。 guides.rubyonrails.org/association_basics.html
  • @wish 检查我的解决方案。它应该适合你。它经过测试。

标签: ruby-on-rails associations ruby-on-rails-5 nested-form-for


【解决方案1】:

我想使用关联和嵌套表单创建记录,现在我可以使用嵌套表单与用户一起创建公司,但我还想为用户创建 user_role。

在创建user_role 之前,您需要将user 提交并保存到db,否则会遇到验证错误。

user_role 未保存,因为您设置的user_id 与已保存的user 不对应

user_role belongs_to 用户。 user_role.user_id 必须对应于现有 useridusers 中一行的字段 id)。如果您尝试保存user_role 对象并且user 尚未保存,您将触发验证错误并且user_role 将不会被保存。在创建 user_role 之前将 user 保存在控制器中。

【讨论】:

  • 你做了很好的尝试,但是,正如我之前告诉你的那样 > 它使用 user_id 和 company_id 创建 user_role,但不包括 role_id 到 user_role 记录中。问题不在于用户对象问题是保存完整记录。
【解决方案2】:

模型

1.company.rb

# put inverse_of otherwise it will throw error. To know more about inverse of go throw docs
has_many :user_roles, inverse_of: :company
has_many :users, through: :user_roles
has_many :roles, through: :user_roles

accepts_nested_attributes_for :user_roles

2.user_role.rb

belongs_to :user
belongs_to :role
belongs_to :company

# user_roles_attributes will accept nested attributes for both user and role
accepts_nested_attributes_for :role
accepts_nested_attributes_for :user

3.user.rb

has_many :user_roles#, inverse_of: :user
has_many :roles, through: :user_roles
has_many :company, through: :user_roles

4.role.rb

has_many :user_roles
has_many :users, through: :user_roles
has_many :companies, through: :user_roles

Companycontroller.rb

def new
    @company = Company.new
    urole = @company.user_roles.build
    urole.build_user
    urole.build_role
end

def create
  @company = Company.new(company_params)
  @company.save
end

private 
def company_params
  # here put associate modal attributes to permit.
  params.require(:company).permit(:company_name,
    user_roles_attributes: [
      role_attributes: [:role_name],
      user_attributes: [:user_name, :email]
    ]
  )
end

form.html.erb

<%= form_for @company, html: { multipart: true } do |f| %>


  <%=f.fields_for :user_roles do |user_roles_builder| %>

    --USER DETAILS--
    <br>
    <%=user_roles_builder.fields_for :user do | user_builder | %>
      <%= render "users_fields", :f => user_builder %>
    <% end %>
    <br>


    -- ROLE DETAILS--
    <br>
    <%=user_roles_builder.fields_for :role do | role_builder | %>
      <%= render "users_fields", :f => role_builder %>
    <% end %>

  <% end %>

  <div class="actions">
    <%= f.submit %>
  </div>

<% end %>

按照这个,它应该对你有用

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-12
    • 2016-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多