Rails 4 STI 继承列未设置

问题描述 投票:0回答:1

我过去使用 STI 没有问题,但在尝试使用自定义继承列时在 Rails 4(4.0.5 和 4.1.4)上遇到过这个问题。问题是该列不会自动设置。

给定:

class Place < ActiveRecord::Base
    self.abstract_class = true
    self.inheritance_column = :category
end

class City < Place
    self.table_name = 'places'
end

City.create location: 'Baltimore'

类别未设置,但我可以手动设置它

City.create location: 'Baltimore', category: 'City'

我不确定是什么问题。 Places 模型只有位置(字符串)和类别(字符串)列。

感谢您的帮助

ruby-on-rails ruby-on-rails-4 single-table-inheritance
1个回答
0
投票

我也为此苦苦挣扎了几分钟。问题是

self.abstract_class = true
.

当您将其设置为 true 时,该类将从 STI 的继承链中消失,并且 Rails 无法正确发现表名。

但是如果你的基类——像我的——是一个抽象类,一个你不想持久化到你的数据库中的类,该怎么办?

简单:在您的基类中添加一个

validates :type, presence: true
,并在您的迁移中创建您的
type
null: false

这个答案来自官方 Rails 文档,这里:


# Consider the following default behaviour:

Shape = Class.new(ActiveRecord::Base)
Polygon = Class.new(Shape)
Square = Class.new(Polygon)

Shape.table_name   # => "shapes"
Polygon.table_name # => "shapes"
Square.table_name  # => "shapes"
Shape.create!      # => #<Shape id: 1, type: nil>
Polygon.create!    # => #<Polygon id: 2, type: "Polygon">
Square.create!     # => #<Square id: 3, type: "Square">

# However, when using abstract_class, Shape is omitted from the hierarchy:

class Shape < ActiveRecord::Base
  self.abstract_class = true
end
Polygon = Class.new(Shape)
Square = Class.new(Polygon)

Shape.table_name   # => nil
Polygon.table_name # => "polygons"
Square.table_name  # => "polygons"
Shape.create!      # => NotImplementedError: Shape is an abstract class and cannot be instantiated.
Polygon.create!    # => #<Polygon id: 1, type: nil>
Square.create!     # => #<Square id: 2, type: "Square">

最后说:

请注意,在上面的示例中,要禁止创建普通多边形,您应该使用

validates :type, presence: true
,而不是将其设置为抽象类。这样,Polygon 将留在层次结构中,Active Record 将继续正确派生表名。

就像我说的,我还在我的迁移中将

null: false
添加到
type
列。这样我就可以确定我的基类永远不会被持久化到数据库中。

© www.soinside.com 2019 - 2024. All rights reserved.