NoMethodError - 使用设计注册的连接 table 中嵌套表单的未定义方法
NoMethodError - undefined method for a nested form from a join table using devise registration
我正在关注 this tutorial 如何在我的 Devise 注册表中嵌套其他模型。我的新控制器出现错误:
'NoMethodError in Users::RegistrationsController#new undefined method `languages_user=' #'。
Languages_Users 是一个连接 table,我想知道这是否是它不起作用的原因,但我不明白解决方案是什么。我想在用户注册时添加 Languages_Users 的 2 个不同记录。
型号:
User.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :role
has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100#" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
validates_presence_of :first_name, :last_name, :location, :nationality, :bio
before_save :assign_role
def assign_role
self.role = Role.find_by name: "user" if self.role.nil?
end
has_many :languages_users
has_many :languages, :through => :languages_users
accepts_nested_attributes_for :languages_users
Language.rb
class Language < ActiveRecord::Base
has_many :languages_users
has_many :users, :through => :languages_users
end
Langauges_user.rb
class LanguagesUser < ActiveRecord::Base
belongs_to :user
belongs_to :language
validates_presence_of :user_id, :language_id, :level
validates :user_id, :uniqueness => {:scope => :language_id, :message => 'can only delcare each language once. Please change the level of the language in Manage Languages.'}
end
控制器:
registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
def new
build_resource({})
self.resource.languages_user = LanguagesUser.new[sign_up_params]
respond_with self.resource
end
def create
@user_id = current_user.id
super
end
def sign_up_params
allow = [:email, :password, :password_confirmation, [languages_user_attributes: [:language_id, :user_id, :level]]]
end
end
用户的相关部分new.html.erb
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<%= f.fields_for :langauges_user do |lu| %>
<%#= lu.text_field :language_id %>
<%= lu.collection_select(:language_id, Language.order('language ASC').all, :id, :language) %><br>
<%= lu.hidden_field languages_user[level], value: 1 %>
<% end %>
<%= f.submit "Sign up" %>
<% end %>
相关路线
Rails.application.routes.draw do
resources :languages_users
devise_for :users, controllers: { registrations: "users/registrations" }
resources :users
get 'languages_users/:id/sign_up', to: 'languages_users#sign_up', as: 'sign_up'
end
我还在学习 - 如果您需要查看其他内容,请告诉我。谢谢!
我对 Devise 的了解还不够快,因为我自己最近才开始使用它,但如果我理解正确的话,这不是与 Devise 相关的问题——只是因为 Devise 的问题而更难修复 self.resource
抽象。
您在一个重要方面偏离了您的教程:在教程中 User
创建了 Company
, 但是 Company
has_many :users
。在你的例子中,User
创建了一个 LanguagesUser
,但在这里,User
has_many :languages_users
。这意味着新的语法。这一行,当前导致您的错误:
self.resource.languages_user = LanguagesUser.new[sign_up_params]
需要遵循:
self.resource.languages_users.build(sign_up_params) #but see below re sign_up_params
或者如果您想立即保存相关资源(我假设不是,因为您现在不在),您可以使用 create
或 create!
而不是 build
.
放在一边
您可能 运行 使用您的 sign_up_params
方法遇到不同的麻烦,该方法似乎也偏离了教程 - 它实际上并未使用 allow
数组将任何内容列入白名单参数,至少如您问题中所写。在任何情况下,请注意他们在实例化 Company
时没有使用它,因此在构建 LanguagesUser
时它可能也不适合目的。
一旦您修复了 sign_up_params
方法,对 sign_up_params[:languages_user_attributes]
的简单调用就可以帮助您完成任务。或者您可以使用自己的参数白名单设置嵌套对象。
我正在关注 this tutorial 如何在我的 Devise 注册表中嵌套其他模型。我的新控制器出现错误:
'NoMethodError in Users::RegistrationsController#new undefined method `languages_user=' #'。
Languages_Users 是一个连接 table,我想知道这是否是它不起作用的原因,但我不明白解决方案是什么。我想在用户注册时添加 Languages_Users 的 2 个不同记录。
型号:
User.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :role
has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100#" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
validates_presence_of :first_name, :last_name, :location, :nationality, :bio
before_save :assign_role
def assign_role
self.role = Role.find_by name: "user" if self.role.nil?
end
has_many :languages_users
has_many :languages, :through => :languages_users
accepts_nested_attributes_for :languages_users
Language.rb
class Language < ActiveRecord::Base
has_many :languages_users
has_many :users, :through => :languages_users
end
Langauges_user.rb
class LanguagesUser < ActiveRecord::Base
belongs_to :user
belongs_to :language
validates_presence_of :user_id, :language_id, :level
validates :user_id, :uniqueness => {:scope => :language_id, :message => 'can only delcare each language once. Please change the level of the language in Manage Languages.'}
end
控制器:
registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
def new
build_resource({})
self.resource.languages_user = LanguagesUser.new[sign_up_params]
respond_with self.resource
end
def create
@user_id = current_user.id
super
end
def sign_up_params
allow = [:email, :password, :password_confirmation, [languages_user_attributes: [:language_id, :user_id, :level]]]
end
end
用户的相关部分new.html.erb
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<%= f.fields_for :langauges_user do |lu| %>
<%#= lu.text_field :language_id %>
<%= lu.collection_select(:language_id, Language.order('language ASC').all, :id, :language) %><br>
<%= lu.hidden_field languages_user[level], value: 1 %>
<% end %>
<%= f.submit "Sign up" %>
<% end %>
相关路线
Rails.application.routes.draw do
resources :languages_users
devise_for :users, controllers: { registrations: "users/registrations" }
resources :users
get 'languages_users/:id/sign_up', to: 'languages_users#sign_up', as: 'sign_up'
end
我还在学习 - 如果您需要查看其他内容,请告诉我。谢谢!
我对 Devise 的了解还不够快,因为我自己最近才开始使用它,但如果我理解正确的话,这不是与 Devise 相关的问题——只是因为 Devise 的问题而更难修复 self.resource
抽象。
您在一个重要方面偏离了您的教程:在教程中 User
创建了 Company
, 但是 Company
has_many :users
。在你的例子中,User
创建了一个 LanguagesUser
,但在这里,User
has_many :languages_users
。这意味着新的语法。这一行,当前导致您的错误:
self.resource.languages_user = LanguagesUser.new[sign_up_params]
需要遵循:
self.resource.languages_users.build(sign_up_params) #but see below re sign_up_params
或者如果您想立即保存相关资源(我假设不是,因为您现在不在),您可以使用 create
或 create!
而不是 build
.
放在一边
您可能 运行 使用您的 sign_up_params
方法遇到不同的麻烦,该方法似乎也偏离了教程 - 它实际上并未使用 allow
数组将任何内容列入白名单参数,至少如您问题中所写。在任何情况下,请注意他们在实例化 Company
时没有使用它,因此在构建 LanguagesUser
时它可能也不适合目的。
一旦您修复了 sign_up_params
方法,对 sign_up_params[:languages_user_attributes]
的简单调用就可以帮助您完成任务。或者您可以使用自己的参数白名单设置嵌套对象。