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