在多态关联的数据库列中存储子类的名称-Rails [英] Store child class's name in database column in polymorphic association - rails

查看:119
本文介绍了在多态关联的数据库列中存储子类的名称-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

因此,如果Carabstract_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆