使用 Formtastic 为一个用户创建多个地址

Create multiple Addresses for one User with Formtastic

我目前在我的 Rails 5 应用程序中有以下设置:

class User < ApplicationRecord
  has_many :addresses
  accepts_nested_attributes_for :addresses
end

class Address < ApplicationRecord
  belongs_to :user
end

对应的控制器是这样的:

class UsersController < ApplicationController
  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)

    if @user.save
      redirect_to users_path
    else
      render 'new', notice: "User could not be created"
    end
  end

  private

  def user_params
    params.require(:user).permit(
      :first_name, :last_name, :email, ...
    )
  end
end

每个用户应该有多个 Addresses(例如,用于计费和送货),我需要在创建用户时设置这些。表格(用 formtastic 制作)看起来像这样(outtake):

= semantic_form_for @user do |user|
  = user.input :first_name
  = user.semantic_fields_for Address.new do |shipping_address|
    = shipping_address.input :city
    = shipping_address.input :usage,
      as: :hidden,
      input_html: { value: 'shipping' }
  = user.semantic_fields_for Address.new do |billing_address|
    = billing_address.input :city
    = billing_address.input :usage,
      as: :hidden,
      input_html: { value: 'billing' }

问题是站点参数中只存在后一个地址,因此只会创建一个。

如何为同一用户创建多个地址?

要创建嵌套记录,您应该为记录播种并将关联传递给 fields_for

例如你会做:

class UsersController < ApplicationController
  # ...
  def new
    @user = User.new
    # if we skipped this step there would be no address inputs on the form.
    @user.addresses.new(value: 'shipping')
    @user.addresses.new(value: 'billing')
  end
end

<%= semantic_form_for(@user) do |f| %>
  # ...
  # fields_for iterates through @user.addresses creating 
  # inputs for each
  <% f.semantic_fields_for :addresses do |a| %>
    <%= a.inputs :street %>
    <%= a.input :value,  as: :hidden %>
  <% end %>
<% end %>

这将给出以下参数散列:

{
  user: {
    addresses_attributes: [
      {
        street: 'Wall Street',
        value: 'shipping'
      },
      {
        street: 'Broadway',
        value: 'billing'
      },
    ]
  }
}

请注意,适当的复数在这里非常重要! 然后您可以将其传递给您的用户模型,accepts_nested_attributes 将完成剩下的工作。

class UsersController < ApplicationController
  # ...
  def create
    @user = User.new(user_params)
    if @user.save
      #...
    else
      # ...
    end
  end

  private
    def user_params
      params.require(:user)
            .permit(:email, :password, addresses_attributes: [:value, :street, :city]) # etc
    end
end