我在实现具有has_one :through
关联的嵌套表单时遇到了一些麻烦。
# model: member.rb
belongs_to :user
has_one :academic
# model: user.rb
has_one :member
has_one :academic, through: :member
accepts_nested_attributes_for :member, reject_if: :all_blank
accepts_nested_attributes_for :academic, reject_if: :all_blank
# model: academic.rb
belongs_to :member
belongs_to :user
# users_controller.rb
def new
@user = User.new
@user.build_member
@user.build_academic
end
我也尝试过:
@user.member.build_academic
# new.html.erb
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |ff| %>
<%= ff.text_field :email %>
# member belongs to user so I can call a fields_for
<% ff.fields_for :member do |f| %>
<%= f.text_field :name %>
# this part is not shown. What is wrong with my association?
<% f.fields_for :academic do |a| %>
<%= a.text_field :major %>
<% end %>
<% end %>
<% end %>
我已经看了一下Rails文档。第一个fields_for
显示在页面中(:member
),但第二个:academic
与has_one :through
关联,未显示在页面中。< / p>
任何帮助将不胜感激。谢谢。
答案 0 :(得分:2)
如果您想通过关系构建数据,则必须在构建时传递相关数据:
#app/models/member.rb
class Member < ActiveRecord::Base
belongs_to :user
has_one :academic
accepts_nested_attributes_for :academic
end
#app/models/user.rb
class User < ActiveRecord::Base
has_one :member
has_one :academic, through: :member
accepts_nested_attributes_for :member
end
#app/models/academic.rb
class Academic < ActiveRecord::Base
belongs_to :member
belongs_to :user
end
这将允许您执行以下操作:
#app/controllers/members_controller.rb
class MembersController < ApplicationController
def new
@member = Member.new
@member.build_member.build_academic
end
def create
@member = Member.new member_params
@member.save
end
private
def member_params
params.require(:member).permit(:x, :y, :z, academic_attributes: [:some, :attributes, member_attributes:[...]])
end
end
这将允许以下内容:
#app/views/users/new.html.erb
<%= form_for @user do |f| %>
<%= f.fields_for :member do |m| %>
<%= f.text_field :name %>
...
<%= m.fields_for :academic do |a| %>
<% a.text_field :name %>
...
<% end %>
<% end %>
<%= f.submit %>
<% end %>
这适用于构建新的member
对象,以及来自academic
的新user
对象。虽然不是严格要求的,但看起来它可能会以某种形式对你有所帮助。
如果你想做你所要求的(IE build_member
和build_academic
专属),你需要摆脱has_one :through
关系...
#app/models/user.rb
class User < ActiveRecord::Base
has_many :memberships
has_many :academics, through: :memberships
end
#app/models/membership.rb
class Membership < ActiveRecord::Base
belongs_to :user
belongs_to :academic
end
#app/models/academic.rb
class Academic < ActiveRecord::Base
has_many :memberships
has_many :users, through: :memberships
end
问题是你基本上是在尝试为直接关联(member
)和建立间接关系(academic
)。
如果您想要独占构建, 可以使它们与您的主模型直接关联。以上应该允许您执行以下操作:
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
@user = User.new
@user.members.build.academics.build
end
end
就像我的顶级示例一样,这将通过您的表单传递嵌套数据 - 如果您想完全独占,请执行此操作:
#app/models/user.rb
class User < ActiveRecord::Base
has_one :member
has_one :academic
has_and_belongs_to_many :academics
end
#app/models/member.rb
class Member < ActiveRecord::Base
belongs_to :user
end
#app/models/academic.rb
class Academic < ActiveRecord::Base
belongs_to :user
has_and_belongs_to_many :users
end
这将允许以下内容:
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
@user = User.new
@user.build_member
@user.build_academic
end
def create
@user = User.new user_params
@user.save
end
private
def user_params
params.require(:user).permit(:user, :params, member_attributes: [], academic_attributes:[])
end
end
答案 1 :(得分:1)
为了将来参考或任何有相同问题的人,我找到了解决此问题的方法,以防您有相同的结构。
我可以通过转到表单前的view
并写下:
<% resource.member.build_academic %>
在我的情况下,resource
是由devise
设置的User
,用于身份验证的Rails gem。
并且您不需要引用模型中的任何:through
或任何内容。
这不是最有效的方式,但我还没有找到任何其他解决方案。希望它有所帮助。