#ruby-on-rails #ruby #ruby-on-rails-3 #class #single-table-inheritance
#ruby-on-rails #ruby #ruby-on-rails-3 #класс #наследование одной таблицы
Вопрос:
Я использую Ruby on Rails 3 и реализовал рабочее наследование одной таблицы следующим образом:
class User < ActiveRecord::Base
# Schema Information
#
# Table name: User
#
# id : integer
# type : string
# children_user_id: integer
...
end
class UserAdmin < User
# Schema Information
#
# Table name: UserAdmin
#
# id : integer
# special_field1 : string
# special_field2 : string
# ...
...
end
class UserCommon < User
# Schema Information
#
# Table name: UserCommon
#
# id : integer
# another_field1 : string
# another_field2 : string
# ...
...
end
Я хотел бы знать, выполняется ли при создании UserAdmin
записи (или UserCommon
записи) в User
таблице следующее
UserAdmin.create(:children_user_id => "1")
# or UserCommon.create(:children_user_id => "1")
можно каким-то образом «автоматически» создать (возможно, «Rails Way«!) новую запись также в UserAdmin
таблице (или UserCommon
table), которая имеет свои собственные поля (на уровне базы данных эти поля являются столбцами). Я хотел бы сделать это для того, чтобы «лучше обрабатывать» UserAdmin
, потому что этот класс имеет другие атрибуты UserCommon
класса.
Если это возможно, как я могу это сделать (возможно, используя инструкции модели ассоциации, обратные вызовы, полиморфизм, …)? У вас есть какие-нибудь советы по этому вопросу?
Ответ №1:
Особенность наследования одной таблицы в том, что оно основано на единой табличной модели, что неудивительно, поэтому у вас не может быть разных классов, использующих разные таблицы.
Обычно «Rails Way» заключается в объединении всех возможных полей, которые требуются, в одну таблицу и использовании STI для решения проблем сопоставления данных и проверки для вас. Однако существуют ограничения на то, что оно может скрывать от приложения, поскольку обычно определение поля означает, что оно может использоваться любым из классов, привязанных к этой таблице. Большинство людей не считают это проблемой.
Что вы, вероятно, хотите сделать, так это создать запись, к которой присоединяются в зависимости от типа пользователя, например:
class User < ActiveRecord::Base
end
class AdminUser < User
belongs_to :admin_profile
end
class CommonUser < User
belongs_to :common_profile
end
Для этого потребовалась бы users
таблица, имеющая столбец admin_profile_id
and common_profile_id
, в котором таблицы admin_profiles
и common_profiles
содержат требуемые дополнительные поля.
Атрибуты в этих таблицах могут быть сопоставлены обратно в базовый класс с помощью delegate
метода по мере необходимости.
Перемещение дополнительных полей в отдельную таблицу может помочь разделить вещи, но это также означает, что чтение будет медленнее из-за требуемого объединения и увеличивается вероятность несоответствия записей из-за того, что одна часть отсутствует или устарела.
Обычно вы нормально загружаете все связанные с пользователем поля в одну таблицу, даже если многие из этих полей используются нечасто. Стоимость хранения нулевого поля обычно невелика в схеме вещей, и если таких полей не сотни, дополнительная сложность, с которой сталкивается разработчик, минимальна, меньшая цена, которую приходится платить, чем постоянно создавать записи парами и ссылаться на них.
Комментарии:
1. Возможно, вы что-то забыли после этой фразы: «Атрибуты в этих таблицах могут быть сопоставлены обратно в базовый класс с помощью». В любом случае, спасибо.
2. Вы правы. Я имел в виду «может быть отображен обратно в базовый класс с помощью
delegate
метода»