Rails Has_many协会

时间:2012-07-30 13:55:16

标签: ruby-on-rails ruby ruby-on-rails-3 associations

我有一些问题让我感到困惑,需要回答。所有内容都与以下教程Two Many-to-Many

相关

问题1

使用has_many的连接表是否需要拥有ID?或者删除id的最佳做法?并添加一个索引并使用另外两个主键并将其设置为唯一且一起?

问题2

如何在创建表的迁移中完成?

问题3

完成这些关系模型并更新数据后。我想在每次更新时创建一组新数据(以保存数据)。控制器如何在更新中创建新的创建模型?

问题4

在中间表中,我想设置属性如果有一个可见的true或false,我怎样才能设置不仅仅是第三个表而且还有第二个表参数

2 个答案:

答案 0 :(得分:3)

首先......谨慎一点:轨道广播非常古老。在那一集中可能存在语法上的东西,这些东西已经被新版本的rails赋予了日期。

问题1

如果您使用的是has_many through方法,那么必须在连接模型中有一个id列,因为您使用的是完整的模型。正如Ryan在剧集中提到的那样,如果您需要跟踪其他信息,您将选择此方法。如果使用has_and_belongs_to_many方法,则表中不会有id列。
如果你想要在你的多对多关联中不允许复制的检查(即允许将项目a与项目b配对并再次允许项目a到项目b的另一个记录),你可以使用一个简单的验证具有范围的行:

validates_uniqueness_of :model_a_id, :scope => [:model_b_id]


问题2

您可以使用此代码

在迁移中添加索引
add_index :table_name, [ :join_a_id, :join_b_id ], :unique => true, :name => 'by_a_and_b'

这将插入到create_table语句下面的更改块中(但不在该create_table块中)。有关详细信息,请查看此问题:In a join table, what's the best workaround for Rails' absence of a composite key?

问题3

我并不完全清楚你想要完成什么,但如果你想在每次将新记录插入连接模型时采取某些行动,我会使用after_create活动记录钩子。这看起来像这样。

class YourJoinModel < ActiveRecord::Base

  after_create :do_something

  def do_something
    puts "hello world"
  end
end

每次创建新记录时都会调用该函数do_something。

问题4

使用has_many through方法可以访问您在关系两侧的模型中定义的其他属性。例如,如果您有此设置:

class Factory < ActiveRecord::Base
  has_many :widgets, :through => :showcases
end

class Widget < ActiveRecord::Base
  has_many :factories, :through => :showcases
end

class Showcases < ActiveRecord::Base
  belongs_to :factory
  belongs_to :widget

  attr_accessiable :factory_id, :widget_id, :visible
end

你可以说像

widget = Widget.first
shown = widget.showcases
shown.first.visible

shown = widget.showcases.where( :visible=> true )

您还可以访问其他协会:

shown.first.factory

答案 1 :(得分:0)

在关联中拥有id列的原因是它为您提供了一种删除该特定关联的方法,而无需考虑您自己与该关系的关系。如果没有该标识符,则在指定所有外键之外很难定义关联。

对于一个简单的情况,你的密钥只有两个组件,这不是一个很大的区别,但通常你会有三个或更多作为你的唯一约束的一部分,而且事情变得棘手。

拥有id也会使这种关系成为一流的模型。当您操纵具有关联元数据的元素时,这可能很有用。这也意味着您可以在以后毫不费力地添加元数据。这就是你的“问题4”的意思。将这些属性添加到连接模型。

通常,连接模型的创建方式与任何其他模型一样。主键是id,您可以创建一系列辅助键:

create_table :example_things |t|
  t.integer :example_id
  t.integer :thing_id
end

add_index :example_joins, [ :example_id, :thing_id ], :unique => true
add_index :example_joins, :thing_id

unique索引用于防止重复并允许查找密钥对。辅助用作提取给定example_id的所有thing_id的方法。

在连接模型上操作元数据的常用方法是直接获取它们:

@example_things = @example.example_things.includes(:thing)

这会加载与示例关联的ExampleThing和Thing模型。