Rails 3 has_many 通过 3 个表

Posted

技术标签:

【中文标题】Rails 3 has_many 通过 3 个表【英文标题】:Rails 3 has_many through with 3 tables 【发布时间】:2013-02-07 21:34:42 【问题描述】:

用这个来敲我的头,我问过类似的问题,但无济于事。所以我有三张桌子 Superheros、Powers 和 Teams。一个超级英雄可以有很多权力和很多团队,一个权力可以关联很多超级英雄,一个团队由很多超级英雄组成。我决定将这些保存到一个大关系表(我称之为 Marvel)

这是我设置的:

class Superhero < ActiveRecord::Base
  attr_accessible :name, :power_ids, :team_ids, :attributes_marvels

  has_many :marvels, :dependent => :destroy
  has_many :powers, :through => :marvels
  has_many :teams, :through => :marvels
  accepts_nested_attributes_for :marvels
end

class Power < ActiveRecord::Base
  attr_accessible :name

  has_many :marvels, :dependent => :destroy
end

class Team < ActiveRecord::Base
  attr_accessible :name

  has_many :marvels, :dependent => :destroy
end

class Marvel < ActiveRecord::Base
  attr_accessible :power_id, :superhero_id, :team_id

  belongs_to :superhero
  belongs_to :power
  belongs_to :team
end

这是创建超级英雄的表格:

<%= form_for(@superhero) do |f| %>
 <div class="field">
  <%= f.label :name %><br />
  <%= f.text_field :name %>
 </div>
<div class="field">
 <p>Please select which team you work for:</p>
 <%= f.collection_select(:team_ids, Team.all(:order=>:name), :id, :name, :prompt => true) %>
 </div>
 <div class="field">
<p>Please check all powers that apply to you.</p>
<% Power.all.each do |power| %>
     <label class="checkbox">
     <%= check_box_tag "superhero[power_ids][]", power.id, @superhero.power_ids.include?(power.id) %>
     <%= power.name %>
    </label>
    <% end %>
 </div>
 <div class="actions">
  <%= f.submit %>
 </div>
<% end %>

超级英雄的控制器

  def new
   @superhero = Superhero.new
  end

  def create
   @superhero = Superhero.new(params[:superhero])
  end

我创建这种方式是因为我希望能够在表单中询问(复选框)权力列表,(下拉)团队列表,现在根据这些标准向我显示超级英雄列表。

我几乎可以正常工作,但保存时遇到问题,我注意到在记录器文件中它给了我这个:

Parameters: "utf8"=>"✓", "authenticity_token"=>"sgD0NIjDM8QhMdzSsb7M/+PFd+FxMtNeOGukrdw9qFA=", "superhero"=>"name"=>"Storm", "team_ids"=>"3", "power_ids"=>["1"], "commit"=>"Create Superhero"

INSERT INTO "superheros" ("created_at", "name", "updated_at") VALUES (?, ?, ?)  [["created_at", Thu, 07 Feb 2013 19:59:24 UTC +00:00], ["name", "Storm"], ["updated_at", Thu, 07 Feb 2013 19:59:24 UTC +00:00]]

INSERT INTO "marvels" ("created_at", "power_id", "superhero_id", "team_id", "updated_at") VALUES (?, ?, ?, ?, ?)[0m  [["created_at", Thu, 07 Feb 2013 19:59:24 UTC +00:00], ["power_id", nil], ["superhero_id", 8], ["team_id", 3], ["updated_at", Thu, 07 Feb 2013 19:59:24 UTC +00:00]]

INSERT INTO "marvels" ("created_at", "power_id", "superhero_id", "team_id", "updated_at") VALUES (?, ?, ?, ?, ?)  [["created_at", Thu, 07 Feb 2013 19:59:24 UTC +00:00], ["power_id", 1], ["superhero_id", 8], ["team_id", nil], ["updated_at", Thu, 07 Feb 2013 19:59:24 UTC +00:00]]

为什么要插入两次,为什么可以清楚地看到参数中的值时有Nil值?

【问题讨论】:

【参考方案1】:

您需要在表格的两侧创建依赖关系:

class Superhero < ActiveRecord::Base
  attr_accessible :name, :power_ids, :team_ids, :attributes_marvels

  has_many :marvels, :dependent => :destroy
  has_many :powers, :through => :marvels
  has_many :teams, :through => :marvels
  accepts_nested_attributes_for :marvels
end

class Power < ActiveRecord::Base
  attr_accessible :name

  `has_many :superheros, :through => :marvels`
  has_many :marvels, :dependent => :destroy
end

class Team < ActiveRecord::Base
  attr_accessible :name

  `has_many :superheros, :through => :marvels`
  has_many :marvels, :dependent => :destroy
end

class Marvel < ActiveRecord::Base
  attr_accessible :power_id, :superhero_id, :team_id

  belongs_to :superhero
  belongs_to :power
  belongs_to :team
end

通过这种方式,您可以在 Marvels 中为每个模型添加 ID 密钥,并且您可以访问它们,请在关联指南中查看

【讨论】:

我有同样类型的问题,但这里有点复杂:***.com/questions/26028291/… Any adice?

以上是关于Rails 3 has_many 通过 3 个表的主要内容,如果未能解决你的问题,请参考以下文章

Has_many:通过 Rails 4 实例变量不起作用

在has_many中过滤子对象:通过Rails 3中的关系

带有has_many的Rails嵌套表单:通过,如何编辑连接模型的属性?

Rails 中的 has_many 关联迁移

Rails:为啥“has_many ...,:通过=> ...”关联导致“NameError:未初始化的常量...”

Ruby-on-Rails:多个 has_many :通过可能吗?