Rails 5: лучший способ переопределить сопоставление имен между моделями и именами таблиц SQL?

У меня есть мой 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

Это тоже не сработало. Есть идеи о лучшем способе сделать это?

2 ответа

Я решил эту проблему, добавив Концерн, который реализует table_name Функция для каждой модели.

Основная причина, почему ваш подход потерпел неудачу, был из-за этой линии 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 будут продолжать выводить правильное имя таблицы. Конечно, для нескольких моделей вам нужно создать проблему, а затем включить ее во все нужные модели.

Вы можете прочитать больше об этом поведении здесь

Другие вопросы по тегам