Rails 4.2.4 / 设计 - 如何允许嵌套属性

Rails 4.2.4 / Devise - How to allow nested attributes

我在尝试使用 Devise 清除嵌套表单的某些参数时遇到了一些问题。这是我的代码,最后是对我已经尝试过的内容的解释。

我在 SO 中找到了一堆答案,但它们似乎都指向 put :address_attributes => [:etc],但它对我不起作用。

用户模型

class User < ActiveRecord::Base

  has_many :addresses, dependent: :destroy
  has_many :phones, dependent: :destroy

  accepts_nested_attributes_for :addresses, allow_destroy: true
  accepts_nested_attributes_for :phones, allow_destroy: true

end

地址

class Address < ActiveRecord::Base
  belongs_to :user
end

Phone

class Phone < ActiveRecord::Base
  belongs_to :user
end

形式

  .row
    .col-md-3
      %p 2. Complete seus dados pessoais
    .col-md-9
      = simple_form_for @user, url: user_registration_path, method: :patch, class: 'form-inline' do |f|
        = f.input :name, label: 'Nome Completo'
        = f.input :birth_date, label: 'Data de Nascimento', start_year: 1910
        = f.input :cpf, label: 'CPF'
        .row
          = f.simple_fields_for @user_phone do |ff|
            .col-md-4
              = ff.input :country_code, label: 'Código do País'
            .col-md-4
              = ff.input :area_code, label: 'DDD'
            .col-md-4
              = ff.input :number, label: 'Telefone'

        = f.simple_fields_for @user_address do |ff|
          = ff.input :zip_code, label: 'CEP'
          = ff.input :street, label: 'Rua'
          = ff.input :street_number, label: 'Número'
          = ff.input :district, label: 'Bairro'
          = ff.input :complement, label: 'Complemento'
          = ff.input :state_id, collection: @states, label: 'Estado'
          = ff.input :city_id, collection: @cities, label: 'Cidade'
        = f.submit 'Salvar'

Devise 注册控制器

class Users::RegistrationsController < Devise::RegistrationsController
    before_filter :configure_sign_up_params, only: [:create]
    before_filter :configure_account_update_params, only: [:update]

  def configure_account_update_params
    devise_parameter_sanitizer.for(:account_update) do |u| 
      # raise
      u.permit(:username, :name, :birth_date, :cpf, :phone_attributes =>    [:country_code, :area_code, :number], :address_attributes => [:zip_code, :street_number, :street, :district, :complement, :state_id, :city_id])
    end
  end

结束

日志:

    tarted PATCH "/users" for 127.0.0.1 at 2015-10-29 18:31:22 -0200
    Processing by Users::RegistrationsController#update as HTML
      Parameters: {"utf8"=>"✓", "authenticity_token"=>"CiXxFEc9zv6WAf5Ow/Kv8ZDU84lAsdFXmLP0IeDlxGKgbjdOzS2+IlZ3NVFlwDKohQz0ix7m0uXOUGEg2na1HA==", "user"=>{"name"=>"Teste", "birth_date(3i)"=>"29", "birth_date(2i)"=>"10", "birth_date(1i)"=>"2015", "cpf"=>"32323232", "phone"=>{"country_code"=>"55", "area_code"=>"3232", "number"=>"323232"}, "address"=>{"zip_code"=>"32212", "street"=>"dasdasdasdas", "street_number"=>"dasdasdasd", "district"=>"sdasdasdas", "complement"=>"asdasdasdsa", "state_id"=>"2", "city_id"=>"1"}}, "commit"=>"Salvar"}
      User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" =   ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
      User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" =  LIMIT 1  [["id", 1]]
    Unpermitted parameters: phone, address
       (0.1ms)  BEGIN
       (0.1ms)  COMMIT
    Redirected to http://localhost:3000/
    Completed 302 Found in 26ms (ActiveRecord: 0.7ms)

如果它尝试输入 :address_attributes => [:etc],我会得到未经许可的参数。如果我只尝试 :address => [:etc],我会得到 "Attribute address not found for user"。

我试过输入复数形式 (:addresses_attributes) 但没用。

Devise 控制器已在路由中配置,并允许我编辑模型本身的所有字段,问题仅出现在嵌套模型中。

有人能帮忙吗?

您遇到的主要问题是您的 fields_for 没有正确初始化您的嵌套属性 - 参数应该分别传递 phones_attributesaddresses_attributes

因此,您最好使用以下内容:

#config/routes.rb
devise_for :users, controller: { registrations: "registrations" }

#app/controllers/registrations_controller.rb
class RegistrationsController < ApplicationController
   def new
     build_resource({})
     self.resource.phones.build
     self.resource.addresses.build
     respond_with self.resource
   end
end

那么在你看来:

#app/views/registrations/new.haml
...
= f.simple_fields_for :phones do |ff|
   ...
= f.simple_fields_for :addresses do |ff|
   ...

这应该设置要通过模型传递的正确属性。