Ruby on rails has_one:through-without-join模型

Ruby on rails has_one:through-without-join模型,ruby-on-rails,activerecord,Ruby On Rails,Activerecord,我有一个Rails项目,它实现了许多孤立的引擎 主发动机(始终存在) 扩展引擎#1(扩展主引擎的可选插件) 扩展引擎#2(扩展主引擎的可选插件) 等等 长话短说,我需要有扩展引擎来添加与主引擎的模型有关系的模型 扩展不应该修改任何其他引擎的物理表,但是扩展没有理由不能创建它们自己的表作为连接表来引用主引擎的表 为了简单起见,下面说明了我要做的事情 主发动机 …/app/models/models/user.rb 我想知道是否有一种方法可以让has_one像has_和_belient_to _ma

我有一个Rails项目,它实现了许多孤立的引擎

  • 主发动机(始终存在)
  • 扩展引擎#1(扩展主引擎的可选插件)
  • 扩展引擎#2(扩展主引擎的可选插件)
  • 等等
  • 长话短说,我需要有扩展引擎来添加与主引擎的模型有关系的模型

    扩展不应该修改任何其他引擎的物理表,但是扩展没有理由不能创建它们自己的表作为连接表来引用主引擎的表

    为了简单起见,下面说明了我要做的事情

    主发动机 …/app/models/models/user.rb 我想知道是否有一种方法可以让
    has_one
    has_和_belient_to _many
    那样工作,其中连接表是推断的,但不需要指定

    谢谢

    澄清更新:
    PrimaryEngine::User
    可以有一辆车,但是
    VehicleeEngine::vehicle
    可以有许多不同的用户

    所以,我想你要问的不是要推断直通(因为有很多人推断直通),而是要在没有模型的情况下使用链接表

    我不这么认为。使用:through选项时,ActiveRecord将转到:through中命名的关联,然后转到该关联的模型(因此through关联和through模型都需要存在)

    继续创建空模型。这没什么大问题

    我想知道是否有一种方法可以让has_one像has_和_belies_to _many那样工作,其中连接表是推断的,但不需要指定

    如果您有一对一的关系,您可能不需要联接表,因为您可以通过在任一表中都有一个外键来实现这一点。但是,你说你不能做外键

    如果您知道以后需要切换到一对多或多对多,那么您可能会使用具有id列的成熟联接模型。(一般规则是HABTM适用于只有两列的联接表—要联接的表的两个外键,否则联接表将成为一个模型,您可以根据需要通过该模型执行has_许多操作等。)这就是@Marlin_Pierce所说的

    要使has_像一个单一的HABTM一样工作,您将覆盖它的默认行为,这将使其他人感到困惑。不要这样做

    因此,我建议只向模型中添加其他方法,使其更像has_one:

    has_and_belongs_to_many :vehicles
    
    def vehicle
      vehicles.first
    end
    
    def vehicle=(vehicle)
      vehicles = vehicle ? [vehicle] : []
    end
    
    HABTM和has_many总是返回一个空数组,如果关系是有效的,即使没有返回任何行,那么您也不需要执行
    try
    或在getter中检查nil


    但是,考虑到这一点,我认为你真正想要的是
    有一个:车辆,通过::车辆\发动机\用户\车辆
    。这需要一个连接模型,但这是“rails方式”来完成您想要做的事情,并且已经描述过了。然后,如果您正在编写一个gem来实现这一点,为了在需要时使其更容易,您可以编写生成器来创建连接模型和相关的迁移。

    嗨,Gary,谢谢您的评论。不幸的是,我不能修改父表,只能修改引擎自己的表。这意味着我不能将
    车辆id
    放在
    主发动机用户
    表中。@Ryan\u Griffith明白。其他人会得出这个答案,并希望确保我为他们留下这个选择。对于您来说,我建议您只需在模型上添加一个方法,以获得HABTM结果集的
    。首先,如果您确定不需要联接模型,请使用
    # .../vendor/engines/vehicle_engine/app/models/vehicle.rb
    module VehicleEngine
        Vehicle < ActiveRecord::Base
        End
    end
    
    # .../vendor/engines/vehicle_engine/config/initializers/user_extension.rb
    ...
    PrimaryEngine::User.class_eval do 
        has_one :vehicle, :through => :vehicle_engine_users_vehicles
    end
    ...
    
    CREATE TABLE vehicle_engine_users_vehicles
    (
      primary_engine_user_id integer NOT NULL,
      vehicle_id integer NOT NULL
    )
    
    has_and_belongs_to_many :vehicles
    
    def vehicle
      vehicles.first
    end
    
    def vehicle=(vehicle)
      vehicles = vehicle ? [vehicle] : []
    end