Rails 嵌套属性和 has_many :through associations not showing fields_for
Rails nested attributes and has_many :through associations not showing fields_for
这是我的模型:
class Company < ActiveRecord::Base
has_many :roles, :dependent => :destroy, :inverse_of => :user
has_many :users, :through => :roles
validates :name, presence: true
end
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :roles, :dependent => :destroy, :inverse_of => :user
has_many :companies, :through => :roles
accepts_nested_attributes_for :roles, :limit => 1, :allow_destroy => true
end
class Role < ActiveRecord::Base
belongs_to :user, :inverse_of => :roles
belongs_to :company, :inverse_of => :roles
#accepts_nested_attributes_for :companies, :limit => 1, :allow_destroy => true
accepts_nested_attributes_for :company
end
这里的想法是公司是独一无二的,用户可以通过一个角色关联到多个公司。我在用户模型上设置了用于身份验证和注册的设计。一切正常,我可以注册为新用户。
我想在注册过程中添加公司名称。我正在尝试嵌套形式:
<%= form_for(resource, :html => {:class => "form-signin" }, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render partial: "shared/flash" %>
<%= devise_error_messages! %>
<h1 class="form-signin-heading text-muted">Register</h1>
<%= f.email_field :email, class: "form-control", placeholder: "Email", autofocus: true %>
<%= f.password_field :password, class: "form-control", placeholder: "Password", autocomplete: "off" %>
<%= f.password_field :password_confirmation, class: "form-control", placeholder: "Password Confirmation", autocomplete: "off" %>
<%= f.fields_for :roles do |r| %>
<%= r.fields_for :company do |c| %>
<%= c.text_field :name, class: "form-control", placeholder: "Company", autocomplete: "off" %>
<% end %>
<% end %>
<button class="btn btn-lg btn-primary btn-block" type="submit">
Register
</button>
<% end %>
我发现了一些其他 SA 答案,这些答案指出需要通过 has_many
通过关联以及一些 single/plural 问题深入研究 accepts_nested_attributes_for
。修复这些后,我的表单加载没有错误,除了 fields_for
块是空的。
现在我承认我的模型可能是这里的问题。我从几年前开发的一个应用程序中复制了代码,所以我忘记了为什么要这样做。
归根结底,我想在用户注册时创建公司和角色。我计划将角色的创建添加到公司控制器,但我需要至少先创建公司。
更新
我做了更多挖掘并将我的表格更新为:
<% company = resource.companies.build %>
<%= f.fields_for :company, company do |c| %>
<%= c.text_field :name, class: "form-control", placeholder: "Company", autocomplete: "off" %>
<% end %>
我意识到我的 Devise 控制器没有构建嵌套的 Company 资源。我想远离自定义 Devise 控制器。我的表单已提交,我的用户已创建,但我仍然遗漏了一些内容,因为公司和角色未保存。
经过一些挖掘和实验,我是这样解决这个问题的:
型号
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :roles, :dependent => :destroy, :inverse_of => :user
has_many :companies, :through => :roles
accepts_nested_attributes_for :roles, :limit => 1, :allow_destroy => true
end
class Role < ActiveRecord::Base
belongs_to :user, :inverse_of => :roles
belongs_to :company, :inverse_of => :roles
accepts_nested_attributes_for :company
end
class Company < ActiveRecord::Base
has_many :roles, :dependent => :destroy, :inverse_of => :user
has_many :users, :through => :roles
validates :name, presence: true
end
自定义设计注册控制器
class RegistrationsController < Devise::RegistrationsController
# GET /resource/sign_up
def new
build_resource({})
@role = resource.roles.build(role: "owner", active: 1, default_role: 1)
@company = @role.build_company
set_minimum_password_length
yield resource if block_given?
respond_with self.resource
end
protected
def sign_up_params
params.require(:user).permit(:email, :password, :password_confirmation, roles_attributes: [ company_attributes: [ :id, :name ] ] )
end
end
HTML
<%= form_for(resource, :html => {:class => "form-signin" }, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render partial: "shared/flash" %>
<%= devise_error_messages! %>
<h1 class="form-signin-heading text-muted">Register</h1>
<%= f.email_field :email, class: "form-control", placeholder: "Email", autofocus: true %>
<%= f.password_field :password, class: "form-control", placeholder: "Password", autocomplete: "off" %>
<%= f.password_field :password_confirmation, class: "form-control", placeholder: "Password Confirmation", autocomplete: "off" %>
<%= f.fields_for :roles, resource.roles.build do |r| %>
<%= r.fields_for :company, resource.roles.build.build_company do |c| %>
<%= c.text_field :name, class: "form-control", placeholder: "Company", autocomplete: "off" %>
<% end %>
<% end %>
<button class="btn btn-lg btn-primary btn-block" type="submit">
Register
</button>
<% end %>
我想我把模型和关联搞砸了。现在 form_for
神奇地起作用了。
我要 post 另一个单独的问题,但当我仍然无法弄清楚时:
- 为什么我在controller中设置的@role和@company在视图中起作用HTML?
- 如何设置额外的角色属性?我在控制器和视图的构建阶段都尝试过,但没有成功。
这是我的模型:
class Company < ActiveRecord::Base
has_many :roles, :dependent => :destroy, :inverse_of => :user
has_many :users, :through => :roles
validates :name, presence: true
end
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :roles, :dependent => :destroy, :inverse_of => :user
has_many :companies, :through => :roles
accepts_nested_attributes_for :roles, :limit => 1, :allow_destroy => true
end
class Role < ActiveRecord::Base
belongs_to :user, :inverse_of => :roles
belongs_to :company, :inverse_of => :roles
#accepts_nested_attributes_for :companies, :limit => 1, :allow_destroy => true
accepts_nested_attributes_for :company
end
这里的想法是公司是独一无二的,用户可以通过一个角色关联到多个公司。我在用户模型上设置了用于身份验证和注册的设计。一切正常,我可以注册为新用户。
我想在注册过程中添加公司名称。我正在尝试嵌套形式:
<%= form_for(resource, :html => {:class => "form-signin" }, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render partial: "shared/flash" %>
<%= devise_error_messages! %>
<h1 class="form-signin-heading text-muted">Register</h1>
<%= f.email_field :email, class: "form-control", placeholder: "Email", autofocus: true %>
<%= f.password_field :password, class: "form-control", placeholder: "Password", autocomplete: "off" %>
<%= f.password_field :password_confirmation, class: "form-control", placeholder: "Password Confirmation", autocomplete: "off" %>
<%= f.fields_for :roles do |r| %>
<%= r.fields_for :company do |c| %>
<%= c.text_field :name, class: "form-control", placeholder: "Company", autocomplete: "off" %>
<% end %>
<% end %>
<button class="btn btn-lg btn-primary btn-block" type="submit">
Register
</button>
<% end %>
我发现了一些其他 SA 答案,这些答案指出需要通过 has_many
通过关联以及一些 single/plural 问题深入研究 accepts_nested_attributes_for
。修复这些后,我的表单加载没有错误,除了 fields_for
块是空的。
现在我承认我的模型可能是这里的问题。我从几年前开发的一个应用程序中复制了代码,所以我忘记了为什么要这样做。
归根结底,我想在用户注册时创建公司和角色。我计划将角色的创建添加到公司控制器,但我需要至少先创建公司。
更新
我做了更多挖掘并将我的表格更新为:
<% company = resource.companies.build %>
<%= f.fields_for :company, company do |c| %>
<%= c.text_field :name, class: "form-control", placeholder: "Company", autocomplete: "off" %>
<% end %>
我意识到我的 Devise 控制器没有构建嵌套的 Company 资源。我想远离自定义 Devise 控制器。我的表单已提交,我的用户已创建,但我仍然遗漏了一些内容,因为公司和角色未保存。
经过一些挖掘和实验,我是这样解决这个问题的:
型号
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :roles, :dependent => :destroy, :inverse_of => :user
has_many :companies, :through => :roles
accepts_nested_attributes_for :roles, :limit => 1, :allow_destroy => true
end
class Role < ActiveRecord::Base
belongs_to :user, :inverse_of => :roles
belongs_to :company, :inverse_of => :roles
accepts_nested_attributes_for :company
end
class Company < ActiveRecord::Base
has_many :roles, :dependent => :destroy, :inverse_of => :user
has_many :users, :through => :roles
validates :name, presence: true
end
自定义设计注册控制器
class RegistrationsController < Devise::RegistrationsController
# GET /resource/sign_up
def new
build_resource({})
@role = resource.roles.build(role: "owner", active: 1, default_role: 1)
@company = @role.build_company
set_minimum_password_length
yield resource if block_given?
respond_with self.resource
end
protected
def sign_up_params
params.require(:user).permit(:email, :password, :password_confirmation, roles_attributes: [ company_attributes: [ :id, :name ] ] )
end
end
HTML
<%= form_for(resource, :html => {:class => "form-signin" }, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render partial: "shared/flash" %>
<%= devise_error_messages! %>
<h1 class="form-signin-heading text-muted">Register</h1>
<%= f.email_field :email, class: "form-control", placeholder: "Email", autofocus: true %>
<%= f.password_field :password, class: "form-control", placeholder: "Password", autocomplete: "off" %>
<%= f.password_field :password_confirmation, class: "form-control", placeholder: "Password Confirmation", autocomplete: "off" %>
<%= f.fields_for :roles, resource.roles.build do |r| %>
<%= r.fields_for :company, resource.roles.build.build_company do |c| %>
<%= c.text_field :name, class: "form-control", placeholder: "Company", autocomplete: "off" %>
<% end %>
<% end %>
<button class="btn btn-lg btn-primary btn-block" type="submit">
Register
</button>
<% end %>
我想我把模型和关联搞砸了。现在 form_for
神奇地起作用了。
我要 post 另一个单独的问题,但当我仍然无法弄清楚时:
- 为什么我在controller中设置的@role和@company在视图中起作用HTML?
- 如何设置额外的角色属性?我在控制器和视图的构建阶段都尝试过,但没有成功。