为什么rails加入了关于foo_ids方法的关系?

时间:2016-03-24 15:44:17

标签: ruby-on-rails ruby-on-rails-4 join

我有关系has_many - has_many喜欢:

class baz < ActiveRecord::Base
    has_many :foo
    has_many :bar, through: :foo
end

class foo < ActiveRecord::Base
   belongs_to :baz
   belongs_to :bar
end

class bar < ActiveRecord::Base
   has_many :foo
   has_many :baz, through: :foo
end

如果我Baz.first.bar_ids,rails会在条形表上加入而不是在foo表中获取bar_id ...为什么?这是无用的联合

SQL日志:

 SELECT `bar`.id FROM `bar` INNER JOIN `foo` ON `bar`.`id` = `foo`.`bar_id` WHERE `foo`.`baz_id` = 1

预期:

 SELECT [DISTINCT] `foo`.bar_id FROM `foo` WHERE `foo`.`baz_id` = 1

2 个答案:

答案 0 :(得分:1)

如果您需要将关系模型设置为独立实体,则应设置has_many :through关系。如果您需要在连接模型上进行验证,回调或额外属性,则应使用has_many :through。相应的示例将在

下面
class baz < ActiveRecord::Base
    has_many :foo
    has_many :bar, through: :foo
end

class foo < ActiveRecord::Base
   belongs_to :baz
   belongs_to :bar
end

class bar < ActiveRecord::Base
   has_many :foo
   has_many :baz, through: :foo
end

结果应该是这样的:

# baz = Baz.first
# bar = Bar.first

# baz.foo.create(bar: bar)

# baz.bars #= [bar] 

答案 1 :(得分:1)

您的预期结果将返回bar_ids表格中存在的foo,如果您从bar表格中删除了一行,您将始终获得他的ID作为回报。

Rails期望您查找的元素存在于表中。

修改

要更改此行为,您可以将bar_ids方法添加到Baz

class Baz < ActiveRecord::Base
     has_many :foo
     has_many :bar, through: :foo 

     def bar_ids
        Foo.uniq.pluck(:bar_id).where(baz_id: self.id)
     end 
end