Rails嵌套表单错误创建重复字段

时间:2016-02-21 18:10:14

标签: ruby-on-rails ruby devise

我在Rails中有一个创建用户和项目的表单。

以下是用户模型的表单代码:

class User < ActiveRecord::Base
  has_many :projects, :dependent => :destroy
  accepts_nested_attributes_for :projects, allow_destroy: true
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :confirmable, :lockable, :timeoutable

  def with_project
    self.projects.build
    self  
  end  
end

和表单视图:

= form_for [resource_name, resource], url: registration_path(resource_name) do |u|
  = u.fields_for :projects do |p| 
    .field = p.text_field :service
    .field = p.text_field :location

  .field = u.email_field :email

  .actions = u.submit "Click to continue"

和用户registrations_controller.rb

class Users::RegistrationsController < Devise::RegistrationsController

  before_action :configure_permitted_parameters


  def new

    build_resource({}).with_project
    set_minimum_password_length
    yield resource if block_given?
    respond_with self.resource
  end

  def create
    build_resource(sign_up_params)
    resource.save
    yield resource if block_given?
    if resource.persisted?
      if resource.active_for_authentication?
        set_flash_message! :notice, :signed_up
        sign_up(resource_name, resource)
        respond_with resource, location: after_sign_up_path_for(resource)
      else
        set_flash_message! :notice, :"signed_up_but_#{resource.inactive_message}"
        expire_data_after_sign_in!
        respond_with resource, location: after_inactive_sign_up_path_for(resource)
      end
    else
      clean_up_passwords resource
      set_minimum_password_length
      respond_with resource
    end
  end

  private

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) { |u|
      u.permit(:email, project: [:id, :service, :location, :_destroy])
    }
  end

end

表单按预期工作;但是,在没有电子邮件的情况下提交时,该视图会显示:service:location

的两个字段

有关为何发生这种情况的任何想法?

更新 - 这是我的routes.rb(现在的问题是project_fields根本没有出现在我的表单视图中)。

devise_for :users, controllers: {registrations: "users/registrations"}
devise_scope :user do
  root 'users/registrations#new'
end

2 个答案:

答案 0 :(得分:3)

我要在你的控制器上做一个假设,代码可能不是这个。

def new
  @user = User.new.with_projects
end

def create
  @user = User.new(params[:user]).with_projects #this is where your problem is.
end

params[:user]包含project_attributes,它们已分配给项目但不会保留。当您致电with_projects时,它会在您的User个实例上添加另一个未加载的项目。由于projectshas_many字段,因此将其视为集合。所以fields_for基本上对现有项目执行循环,并保持未加载状态。这就是您看到服务和位置的重复字段的原因。你有两个项目。

正如我之前提到的,这可能不完全是你设置的方式,但它 正在发生的事情。

更新

问题已经更新......

问题在于表格。与上述完全相同但发生在不同的地方。表单在new视图(由new操作呈现)中呈现一次,该视图在Project实例上构建User实例。论坛已提交,将Project的一个实例分配给@user。然后create操作失败,因为没有有效的电子邮件字段。 create操作然后呈现创建视图(反过来又会再次呈现form部分。然后表单构建另一个与用户关联的project实例。

您可以通过将问题移动到唯一需要的地方来解决问题。 new行动。def new @user = User.new.with_projects end def create @user = User.new(params[:user]) #..... etc end 参见示例。

完成的代码应该类似于: 控制器:

= form_for [resource_name, resource], url: registration_path(resource_name) do |u|
  // etc.....

形式:

Ctrl + .    from query design to datasheet
Ctrl + ,    from datasheet to query design

答案 1 :(得分:0)

当with_project呈现新动作时,RegistersController可能会再次调用该方法,因此表单会显示两个位置和服务字段。