ruby 将子类的名称存储在多态关联的数据库列中- rails

fykwrbwg  于 2022-11-04  发布在  Ruby
关注(0)|答案(1)|浏览(122)

我有一个类,比如说Car,我从它继承了类Black和Red,如下所示:

class Car::Black < Car
end

class Car::Red < Car
end

现在,还有另一个类,比如说CarPurchase,它有许多两种类型的汽车,其关联如下:


# In Black and Red models:

has_many :car_purchases, as: :purchasable, dependent:destroy

# In CarPurchase model:

belongs_to :purchasable, polymorphic: true

现在,我尝试保存CarPurchases,如下所示:

black_car.car_purchases.new()   # black_car is an object of class Car::Black

我的数据库有一个名为purchasable_type的列。问题是记录保存时的purchasable_type为“Car”,而不是“Car::Black”。我在创建记录时也尝试显式保存purchasable_type。没有成功。请帮助。

cgvd09ve

cgvd09ve1#

你可以这样做:

class Car < ActiveRecord::Base
  self.abstract_class = true
  class Black < Car; end
  class Red < Car; end
end

它存储Car的原因在ActiveRecord::Associations::BelongsToPolymorphicAssociation#replace_keys摘录中定义:

def replace_keys(record)
  super
  owner[reflection.foreign_type] = record.class.base_class.name
end

ActiveRecord::Inheritance::ClassMethods::base_class摘录:

def base_class
  unless self < Base
    raise ActiveRecordError, "#{name} doesn't belong in a hierarchy descending from ActiveRecord"
  end

  if superclass == Base || superclass.abstract_class?
    self
  else
    superclass.base_class
  end
end

因此,如果Carabstract_class,则它将存储Car::Black,否则base_class将解析为Car。将Car变为abstract_class不会失去大部分魔力,例如,Car::Black仍然知道它是table_name

警告使用Car作为abstract_class意味着它不能直接示例化。

例如:

class Car < ActiveRecord::Base
  class Black < Car
  end
end 
Car::Black.base_class.name 

# => Car

Car::Black.table_name

# => "cars"

Car.new 

# New Car record

class Car < ActiveRecord::Base
  self.abstract_class = true
end
Car::Black.base_class.name 

# => Car::Black

Car::Black.table_name

# => "cars"

Car.new

# => NotImplementedError: Car is an abstract class and cannot be instantiated.

相关问题