问题
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
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
Now I'm trying to save the CarPurchases like this:
black_car.car_purchases.new() # black_car is an object of class Car::Black
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.
回答1:
You could do something like this:
class Car < ActiveRecord::Base
self.abstract_class = true
class Black < Car; end
class Red < Car; end
end
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
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
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
.
Caveat using Car
as an abstract_class
means it cannot be instantiated directly.
For Example:
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.
来源:https://stackoverflow.com/questions/45140335/store-child-classs-name-in-database-column-in-polymorphic-association-rails