在多态关联的数据库列中存储子类的名称-Rails [英] Store child class's name in database column in polymorphic association - rails
问题描述
我有一个类,例如Car,我从中继承了Black和Red类,如下所示:
I have a class, say, Car from which I have inherited classes Black and Red as follows:
class Car::Black < Car
end
class Car::Red < Car
end
现在,还有另一类,例如CarPurchase,其中有很多两种汽车.关联如下:
Now, there is another class, say, CarPurchase which has many Cars of both varieties. The associations are as follows:
# In Black and Red models:
has_many :car_purchases, as: :purchasable, dependent:destroy
# In CarPurchase model:
belongs_to :purchasable, polymorphic: true
现在,我正在尝试像这样保存CarPurchases:
Now I'm trying to save the CarPurchases like this:
black_car.car_purchases.new() # black_car is an object of class Car::Black
我的数据库有一个称为purchasable_type的列.问题在于记录是用purchasable_type'Car'而不是'Car :: Black'保存的.我还尝试在创建记录时显式保存purchasable_type.没运气.请帮助.
My database has a column called purchasable_type. The problem is that records are saved with purchasable_type 'Car' and not 'Car::Black'. I tried saving the purchasable_type explicitly also while creating record. No luck. Help please.
推荐答案
您可以执行以下操作:
class Car < ActiveRecord::Base
self.abstract_class = true
class Black < Car; end
class Red < Car; end
end
它存储Car
的原因在 ActiveRecord::Associations::BelongsToPolymorphicAssociation#replace_keys
摘录:
The reason it stores Car
is defined in ActiveRecord::Associations::BelongsToPolymorphicAssociation#replace_keys
Excerpt:
def replace_keys(record)
super
owner[reflection.foreign_type] = record.class.base_class.name
end
和 ActiveRecord::Inheritance::ClassMethods::base_class
摘录:
and ActiveRecord::Inheritance::ClassMethods::base_class
Excerpt:
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
因此,如果Car
是abstract_class
,则它将存储Car::Black
,否则base_class
将解析为Car
.将Car
设为abstract_class
不会失去大部分魔力,例如Car::Black
仍然知道它是table_name
.
So if Car
is an abstract_class
then it will store Car::Black
other wise the base_class
will resolve to Car
. Making Car
an abstract_class
will not lose most of the magic e.g. Car::Black
still knows it's table_name
.
注意,将Car
用作abstract_class
表示无法直接实例化.
Caveat using Car
as an abstract_class
means it cannot be instantiated directly.
例如:
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.
这篇关于在多态关联的数据库列中存储子类的名称-Rails的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!