理解:通过Rails的has_one / has_many的源选项

时间:2011-01-08 04:51:29

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

请帮助我理解:source关联的has_one/has_many :through选项。 Rails API的解释对我来说毫无意义。

  

“指定has_many :through => :queries使用的源关联名称。仅在无法从中推断出名称时才使用它   协会。 has_many :subscribers, :through => :subscriptions会   在:subscribers上查找:subscriberSubscription,   除非给出:source。 “

3 个答案:

答案 0 :(得分:214)

有时,您希望为不同的关联使用不同的名称。如果要用于模型上的关联的名称与:through模型上的关联名称不同,则可以使用:source来指定它。

我认为上面的段落很多比文档中的那个更清晰,所以这是一个例子。我们假设我们有三个模型PetDogDog::Breed

class Pet < ActiveRecord::Base
  has_many :dogs
end

class Dog < ActiveRecord::Base
  belongs_to :pet
  has_many :breeds
end

class Dog::Breed < ActiveRecord::Base
  belongs_to :dog
end

在这种情况下,我们选择命名Dog::Breed,因为我们想要访问Dog.find(123).breeds作为一个不错而方便的关联。

现在,如果我们现在要在has_many :dog_breeds, :through => :dogs上创建Pet关联,我们突然遇到问题。 Rails将无法在:dog_breeds上找到Dog关联,因此Rails不可能知道您想要使用哪个 Dog关联。输入:source

class Pet < ActiveRecord::Base
  has_many :dogs
  has_many :dog_breeds, :through => :dogs, :source => :breeds
end

使用:source,我们告诉Rails :breeds模型上查找名为Dog的关联(因为这是用于{{}的模型1}}),并使用它。

答案 1 :(得分:184)

让我扩展一下这个例子:

class User
  has_many :subscriptions
  has_many :newsletters, :through => :subscriptions
end

class Newsletter
  has_many :subscriptions
  has_many :users, :through => :subscriptions
end

class Subscription
  belongs_to :newsletter
  belongs_to :user
end

使用此代码,您可以执行Newsletter.find(id).users之类的操作来获取简报订阅者的列表。但是,如果您希望更清楚并且能够键入Newsletter.find(id).subscribers,则必须将Newsletter类更改为:

class Newsletter
  has_many :subscriptions
  has_many :subscribers, :through => :subscriptions, :source => :user
end

您正在将users关联重命名为subscribers。如果您未提供:source,则Rails将在Subscription类中查找名为subscriber的关联。您必须告诉它使用Subscription类中的user关联来创建订阅者列表。

答案 2 :(得分:9)

最简单的答案:

表中的关系名称是中间的。