ruby-on-rails - ActiveRecord has_many 通过与 arg 的作用域关联

标签 ruby-on-rails ruby activerecord

我已经看到许多问题的答案,这些问题解决了如何在 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/

相关文章:

ruby-on-rails-3 - 是否有可能在 PostgreSQL 中有一个 hstore 数组

ruby-on-rails - rails : Query all but first record?

javascript - 如何将发布请求发送到 Rails 操作

ruby-on-rails - 验证特定操作的模型

sql - 如何获取关联的关联id为给定值的记录

ruby-on-rails - rails 4 :Error in setting up SignIn Page as root page using Devise

excel - 用于读取/写入 XLSX 并支持命名范围的 Ruby gem

ruby-on-rails - 在 Mongoid 中创建有关对象创建的嵌入式文档

ruby-on-rails - 救援 block 未捕获引发的错误

ruby-on-rails - 如何使用 Rails ActiveRecord 执行 LEFT OUTER JOIN?