1

我有我的 Rails 5 ApplicationRecord

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

和一堆继承自ApplicationRecord. 现在,我希望每个模型名称以自定义方式映射到其数据库表。例如,我可以这样做:

class MyModel < ApplicationRecord
  self.table_name = 'MY_MODELS'   # overrides default 'my_models'
end

但由于所有映射都是可预测的,我想我会在基类中这样做:

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

  def self.table_name
    self.name.underscore.pluralize.upcase
  end
end

...但这不起作用,即使从技术上讲,类方法应该由子类继承。(知道为什么吗?)

我还尝试添加一个执行以下操作的方法:

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

  def self.inherited(subclass)
    subclass.table_name = subclass.name.underscore.pluralize.upcase
  end
end

这也不起作用。知道最好的方法吗?

4

2 回答 2

2

我最终通过添加一个实现table_name每个模型的功能的关注来解决这个问题。

于 2016-03-30T15:53:59.227 回答
1

您的方法失败的主要原因是由于这条线self.abstract_class = true。这条线有什么作用?

它使类成为抽象类。在 Rails 中,抽象模型/类意味着被应用程序中的其他模型继承。它们在您的应用程序的数据库中没有表,它们不能被实例化,即它们不能有对象。此外,所有继承自的模型ApplicationRecord都将从其层次结构中省略。

对此的简单解决方案,即让您的模型包含在您的 ApplicationRecord层次结构中是为您的模型添加验证。所以在你的情况下,这将是:

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

  def self.table_name
    self.name.underscore.pluralize.upcase
  end
end

class MyModel < ApplicationRecord
  validates :type, presence: true
end

添加验证将放入MyModel层次结构中ApplicationRecord,Active Record 将继续派生正确的表名。当然,对于多个模型,您必须创建一个关注点,然后将其包含在您想要的所有模型中。

您可以在此处阅读有关此行为的更多信息

于 2018-09-21T17:55:23.007 回答