我已经看到许多问题的答案,这些问题解决了如何在 ActiveRecord 关联中使用范围 block ,包括将对象本身传递到 block 中,例如...
class Patron < ActiveRecord::Base
has_many :bars,
->(patron) { baz: patron.blah },
foreign_key: :somekey,
primary_key: :somekey
end
class Bar < ActiveRecord::Base
belongs_to :patron,
->(bar) { blah: bar.baz },
foreign_key: :somekey,
primary_key: :somekey
end
这里使用显式主键和外键是由于底层表之间的遗留关系。生产系统中有数以亿计的“赞助人”。
作为对 @TJR 的澄清 - Patron 和 Bar 之间的关系实际上是字段 :somekey 和 :baz(或相反方向的 :blah)上的复合外键。 ActiveRecord 的 :foreign_key 选项不允许数组。
我发现不幸的是,这会阻止后续的 has_many :throughs 按预期工作。
class Patron < ActiveRecord::Base
has_many :bars,
->(patron) { baz: patron.blah },
foreign_key: :somekey,
primary_key: :somekey
has_many :drinks, through: :bars
end
使用直通关联会产生类似...的错误
ArgumentError: wrong number of arguments (0 for 1)
bar 和 drinks 之间的关联是一个经典的 has_many,带有标准的外键和主键 (bar_id, id)。
我想出了一些丑陋的解决方法,使我能够完成所需的功能,但整个事情闻起来很糟糕。到目前为止,其中最好的看起来像
class Patron < ActiveRecord::Base
has_many :bars,
->(patron) { baz: patron.blah },
foreign_key: :somekey,
primary_key: :somekey
def drinks
bars.drinks
end
end
我已经收到现有的 Bar 类,它包含数亿条记录,正如我之前提到的,这使得数据库方面的更改变得困难。
有些帖子似乎建议在 proc 中进行动态字符串评估,以避免必须传入当前赞助人对象 - 但正如其他帖子中提到的那样,这是行不通的。
请告诉我如何通过关系工作来获得 has_many。
最佳答案
我刚刚在 Rails 4.2 中尝试过这种关联。它工作得很好:
class Patron < ActiveRecord::Base
has_many :bars,
->(patron) { where(baz: patron.blah) },
foreign_key: :patron_id,
primary_key: :id
has_many :drinks, through: :bars
end
class Bar < ActiveRecord::Base
belongs_to :patron,
->(bar) { where(blah: bar.baz) },
foreign_key: :patron_id,
primary_key: :id
has_many :drinks
end
class Drink < ActiveRecord::Base
end
检查关联:
> p1 = Patron.first
> p1.drinks
Drink Load (0.8ms) SELECT "drinks".* FROM "drinks" INNER JOIN "bars" ON "drinks"."bar_id" = "bars"."id" WHERE "bars"."patron_id" = 1 AND "bars"."baz" = 1 [["patron_id", 1], ["baz", 1]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Drink id: 3, name: "drink 3", bar_id: 2, created_at: "2017-04-07 03:30:06", updated_at: "2017-04-07 03:30:06">]>
关于ruby-on-rails - ActiveRecord has_many 通过与 arg 的作用域关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35873383/