Rails 5 - Devise - 用户 has_one 关联 - 注册表单中不显示嵌套表单字段

Arg*_*s A 0 ruby ruby-on-rails nested-forms devise ruby-on-rails-5

当我搜索时,这是一个常见问题,但我发现没有一个答案适合我的情况。我已经使用设计建立了一个用户模型,它有两个相关的模型,它有一个详细联系信息和许多地址。嵌套表单适用于地址,但未显示我的联系方式详细信息字段。

我的用户模型如下:

  validates_presence_of :contact_detail, :addresses
  # Include default devise modules. Others available are:
  # :lockable, :timeoutable, :trackable and :omniauthable
  devise :invitable, :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :confirmable

  has_one :contact_detail, dependent: :destroy
  has_many :addresses, dependent: :destroy

  accepts_nested_attributes_for :addresses, 
                                allow_destroy: true

  accepts_nested_attributes_for :contact_detail,
                                allow_destroy: true
Run Code Online (Sandbox Code Playgroud)

联系方式型号只有belongs_to :user

我在我的应用程序控制器上进行了 devise gem 中提到的更改:

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [addresses_attributes: [:street_name, :street_number, :city, :country, :postal_code, :name],
                                                      contact_detail_attributes: [:first_name, :last_name, :description, :telephone, :mobile ]])
  end
end
Run Code Online (Sandbox Code Playgroud)

我的 app/views/devise/registrations/new.html.erb 文件如下所示:

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
...
  <div>
    <% f.fields_for :contact_detail do |contact_detail|%>
      <div class="field">
        <%= contact_detail.label :first_name %>
        <%= contact_detail.text_field :first_name %>
      </div>

      <div class="field">
        <%= contact_detail.label :last_name %>
        <%= contact_detail.text_field :last_name %>
      </div>

      <div class="field">
        <%= contact_detail.label :description %>
        <%= contact_detail.text_area :description %>
      </div>

      <div class="field">
        <%= contact_detail.label :telephone %>
        <%= contact_detail.number_field :telephone %>
      </div>

      <div class="field">
        <%= contact_detail.label :mobile %>
        <%= contact_detail.number_field :mobile %>
      </div>
    <% end %>
  </div>
...
Run Code Online (Sandbox Code Playgroud)

但我的联系方式字段没有显示。有任何想法吗?

max*_*max 6

您必须“播种”关系才能显示关联的输入。fields_for像循环一样工作。如果关联为空或 nil,则块运行 0 次。

通常您会在new控制器的操作中执行此操作:

class UsersController < ApplicationController
  def new
    @user = User.new
    @user.build_contact_detail
  end
end
Run Code Online (Sandbox Code Playgroud)

Devise::RegistrationsController#new在 Devise 中,您可以通过子类化控制器来自定义新操作:

class MyRegistrationsController < Devise::RegistrationsController
  def new
    super do |user|
      user.build_contact_detail
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

super do |user| ... end使用这样一个事实:所有设计控制器操作都会占用一个块并产生资源。这使得自定义它们变得非常容易,而无需复制粘贴整个方法。

然后,您必须更改路由以便使用您的自定义控制器:

Rails.application.routes.draw do
  devise_for :users, controllers: {
    registrations: 'my_registrations'
  }
end
Run Code Online (Sandbox Code Playgroud)