ruby-on-rails - 带有 has_one 的嵌套表单 :through

标签 ruby-on-rails

我在使用 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 

Controller

# 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 :通过关联,页面中不显示。

任何帮助将不胜感激。谢谢。

最佳答案

通过

如果您想通过关系构建数据,则必须在构建关联数据时传递该数据:

#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 %>

这可以从user构建一个新的member对象和一个新的academic对象。虽然严格来说并不符合您的要求,但看起来它可以以某种形式使您受益。


协会

如果您想要执行您所要求的操作(IE build_memberbuild_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

问题是您基本上是在尝试建立直接关联(成员)的关系间接关系(学术) .

如果您想专门构建两者,您必须使它们与您的主模型直接关联。上述内容应该允许您执行以下操作:

#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

关于ruby-on-rails - 带有 has_one 的嵌套表单 :through,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33326030/

相关文章:

ruby-on-rails - Rails 服务器无法运行——这是 mysql2 的问题吗?

ruby-on-rails - 将样式类添加到 select_country 字段

ruby-on-rails - 为什么有created_at和updated_at?

ruby-on-rails - 让 Rails 测试通过

ruby-on-rails - 将resque连接到其他键值数据库而不是redis?

ruby-on-rails - 在 Mac OS X 10.9.5 上安装 Ruby 2.1.3 时检查或清理工作树错误

ruby-on-rails - 在 Rails 4 中检测用户代理 - 读取 HTTP header

javascript - 使用 Minitest 在 Rails 应用程序中测试 Javascript

javascript - Rails 辅助方法似乎正在杀死我的 JQuery 脚本

ruby-on-rails - Rails 3、Action Mailer、附件、form_for、电子邮件