ruby-on-rails - 如何从两个不同的外键访问模型?

标签 ruby-on-rails ruby postgresql ruby-on-rails-4 activerecord

我有两个相关模型,Trip 和 Ride。 Trip 可能有去程或回程。我的 ActiveRecord 模型如下所示:

class Route < ActiveRecord::Base
    has_one :trip
end

class Trip < ActiveRecord::Base
    belongs_to :going_route,     class_name: "Route"
    belongs_to :returning_route, class_name: "Route"
end

但是,当我想从路线访问行程时,这给我带来了一个问题:

Route.first.trip

这会引发 PostgreSQL 错误:

PG::UndefinedColumn: ERROR: column trips.route_id does not exist

我如何告诉 Route 类他的行程在 going_route_idreturning_route_id 下?或者也许有另一种解决方法?

P.S:我一直在寻找类似的问题,有很多,但没有一个与这个问题完全相同并解决了我的问题。如果您有任何关于如何使差异更清晰的提示,尤其是对于标题。 Here是一些类似的问题


编辑:

我也试过使用 lambda,如 matthew's duplicate proposition :

class FavoriteRoute < ActiveRecord::Base
    has_one :favorite_trip, -> (route) { where("going_route_id = :id OR returning_route_id = :id", id: route.id) }
end

这将引发相同的错误。如果我假设我应该使用 find_by 而不是 where 因为我只需要一个结果,我就会遇到另一个我真的不明白的错误:

NoMethodError: undefined method `except' for #<Trip:0x00007f827b9d13e0>

最佳答案

您需要在 belongs_to 关联的反面指定外键 - 即引用外键的 has_one/has_many 端键:

class Trip < ActiveRecord::Base
    # specifying foreign_key here is not needed since AR
    # will deduce that its outbound_route_id
    belongs_to :outbound_route,
      class_name: "Route"
    belongs_to :return_route, 
      class_name: "Route"
end

class Route < ActiveRecord::Base
  has_one :trip_as_outbound,
    class_name: 'Trip',
    foreign_key: :outbound_route_id
  has_one :trip_as_returning,
    class_name: 'Trip',
    foreign_key: :return_route_id

  def trip
    trip_as_outbound || trip_as_returning
  end
end

解决这个问题的一种方法是使用单表继承:

class Route < ApplicationRecord 
end

class Routes::Outbound < ::Route
  self.table_name = 'routes'
  has_one :trip, foreign_key: :outbound_route_id
end

class Routes::Return < ::Route
  self.table_name = 'routes'
  has_one :trip, foreign_key: :return_route_id
end

class Trip < ApplicationRecord
  belongs_to :outbound_route,
    class_name: '::Routes::Outbound'
  belongs_to :return_route,
    class_name: '::Routes::Return'
end

这会给你正确的行程,但有一些奇怪的地方,比如 Routes::Return.all 会给你与 Route.all 相同的结果。

这可以通过在 routes 表中添加一个 type 字符串列来解决。为了提高性能,在类型和 ID 上添加复合索引。

关于ruby-on-rails - 如何从两个不同的外键访问模型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51843178/

相关文章:

ruby-on-rails - 修改设计重置密码错误文本

ruby - 遍历哈希中的多个值并返回一个值

ruby-on-rails - Rails 3 + 乘客 : Rack error

sql - 如何选择任意行的相邻行(在 sql 或 postgresql 中)?

postgresql - 从 PostgreSQL 中的文本字段获取 ascii 字节

ruby-on-rails - 保护 REST 和 JSON

ruby-on-rails - Rails Route 仅带有数字参数

ruby-on-rails - Rails,嵌套属性,无法批量分配错误

ruby - 是否有一些工具或模式可以在 emacs 中重构 ruby​​ 代码?

postgresql - sslcert 和 sslkey 如何在 Kubernetes 中作为环境变量传递?