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_attributes
和 addresses_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|
...
这应该设置要通过模型传递的正确属性。
我在尝试使用 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_attributes
和 addresses_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|
...
这应该设置要通过模型传递的正确属性。