1

我有一个车辆模型:

class Vehicle < ActiveRecord::Base
validates_presence_of :num_of_wheels
validates_presence_of :make
validates_presence_of :model
end

在这个类中,我希望有可扩展数量的车辆类型,例如“乘用车”、“摩托车”、“卡车”,每种类型都有自己独特的强制属性。例如,PassengerCar 可能需要门的数量,而这不适用于 Motorcycle 类型。同时,motorcycles 和passenger_cars 在创建时都应该要求/继承Vehicle 的强制属性。

这里的关键是我无法真正预测可能发明或需要存储的不同类型车辆的数量。所以,我需要一种可扩展的方式来添加新的车辆类型。此外,就 UI 和视图而言,如果我的类型在下拉菜单中不可用,那么能够创建一个新的 Vehicle 类型会很好,并且让 db 填充 Vehicle 类型和将其反映到 UI 中。

用 Rails 建模这种关系的最佳方式是什么?我正在考虑使用 has_one :through 关系,但我不确定这是最好的方法。例如,车辆将分配给操作员。一个人一次只能操作一辆车……所以,我可以说:

class Vehicle < ActiveRecord::Base
has_one :motorcycle, :through => :vehicle_type
has_one :passenger_car, :through => :vehicle_type
has_many :vehicle_types
validates_presence_of :num_of_wheels
validates_presence_of :make
validates_presence_of :model
end

class VehicleType < ActiveRecord::Base
belongs_to :vehicle
belongs_to :passenger_car
belongs_to :motorcycle
end

class PassengerCar < ActiveRecord::Base
belongs_to :vehicle_type
validates_presence_of :doors
end

class Motorcycle < ActiveRecord::Base
belongs_to :vehicle_type
validates_presence_of :saddlebags
end

但是,必须将所有可能的类型添加到 Vehicle 模型中似乎很笨拙,并且由于 Operator 一次只能驾驶一辆 Vehicle,因此将所有其他类型的车辆放在 Vehicle 模型的 :has_one 语句中似乎是多余的。

任何想法都非常感谢!

4

1 回答 1

0

一种选择是使用 Rails 的单表继承机制和附​​加表列(更快)或序列化哈希(如果您想添加新属性,则不需要新迁移)来设置此关系,以针对每个模型的细节. 这是想法:

type向正在创建表的迁移添加一列,vehicles以提示 Rails 您希望使用单表继承:

def change
  create_table :vehicles do |t|
    t.string :type

    # if using serialization
    t.text :parameters

    # if using custom fields
    t.integer :saddlebags
    t.integer :doors

    # ...
  end
end

您将使用 Vehicle 作为基类,从这里开始,您的特定车辆将继承其基本属性:

class Vehicle < ActiveRecord::Base
  validates_presence_of :num_of_wheels, :make, :model

  # if using serialization
  serialize :parameters, Hash

  # ...
end

class PassengerCar < Vehicle
end

class Motorcycle < Vehicle
end

# etc..

现在,当 anOperator分配给车辆时,Rails 将自动恢复适当的类:

# models/Operator.rb
class Operator < ActiveRecord::Base
  has_one :vehicle
end

# in controller action
op = Operator.new
op.vehicle = Motorcycle.new
op.vehicle.save
op.save
# op will now be assigned to a +Motorcycle+ the next time it's loaded

如果您在表中使用其他列,验证将按照您的描述进行。但是,如果您选择将它们序列化为parameters,则最好的选择可能是为每个模型的哈希生成自定义验证器。parameters

于 2012-04-16T01:41:16.643 回答