Несколько представляют наследование в виде таблицы по сравнению с единственным наследованием таблицы в Ruby on Rails

Ahh... nevermind. Это всегда - поиск после того, как вопрос поставлен, который приводит к ответу. Мой объект, который сериализируется, obj и был уже определен. Добавление XMLSerializerNamespace с единственным пустым пространством имен к набору добивается цели.

В VB как это:

Dim xs As New XmlSerializer(GetType(cEmploymentDetail))
Dim ns As New XmlSerializerNamespaces()
ns.Add("", "")

Dim settings As New XmlWriterSettings()
settings.OmitXmlDeclaration = True

Using ms As New MemoryStream(), _
    sw As XmlWriter = XmlWriter.Create(ms, settings), _
    sr As New StreamReader(ms)
xs.Serialize(sw, obj, ns)
ms.Position = 0
Console.WriteLine(sr.ReadToEnd())
End Using

в C# как это:

//Create our own namespaces for the output
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();

//Add an empty namespace and empty value
ns.Add("", "");

//Create the serializer
XmlSerializer slz = new XmlSerializer(someType);

//Serialize the object with our own namespaces (notice the overload)
slz.Serialize(myXmlTextWriter, someObject, ns);
11
задан Benjamin 16 October 2015 в 00:48
поделиться

3 ответа

Учитывая ограниченность информации, я бы сказал, что придерживайтесь STI.

Ключевой вопрос: есть ли в вашем приложении места, где вы хотите рассматривать все типы уведомлений вместе? Если да, то это верный признак того, что вы хотите придерживаться ИППП.

2
ответ дан 3 December 2019 в 04:13
поделиться

Have you considered the mixed model approach?

Where you use single table inheritance for your core notification fields. Then offload all the unique items to specific tables/models in a belongs to/has one relationship with your notification subclasses.

It's a little more overhead to set up, but works out to be pretty DRY, once all the classes and tables are defined. Seems like a pretty efficient way to store things. With eager loading you shouldn't be causing too much additional strain on the database.

For the purposes of this example, lets assume that Emails have no unique details. Here's how it maps out.

class Notification < ActiveRecord::Base
  # common methods/validations/associations
  ...

  def self.relate_to_details
    class_eval <<-EOF
      has_one :details, :class_name => "#{self.name}Detail"
      accepts_nested_attributes_for :details
      default_scope -> { includes(:details) }
    EOF
  end
end

class SMS < Notification
  relate_to_details

  # sms specific methods
  ...
end

class Twitter < Notification
  relate_to_details

  # twitter specific methods
  ...
end

class Email < Notification

  # email specific methods
  ...
end

class SMSDetail < ActiveRecord::Base
  belongs_to :SMS, :class_name => "SMS"           

  # sms specific validations
  ...
end

class TwiterDetail < ActiveRecord::Base
  belongs_to :twitter

  # twitter specific validations
  ...
end

Each of the detail tables will contain a notification ID and only columns that form of communication needs that isn't included in the notifications table. Although it would mean an extra method call to get media specific information.

This is great to know but do you think it's necessary?

Very few things are necessary in terms of design. As CPU and storage space drop in cost so do those necessary design concepts. I proposed this scheme because it provides the best of both STI and MTI, and removes a few of their weaknesses.

As far as advantages go:

This scheme provides the consistency of STI. With tables that do not need to be recreated. В связанной таблице есть несколько десятков столбцов, которые пусты в 75% ваших строк. Вы также можете легко создать подкласс. Если вам нужно создать соответствующую таблицу Details только в том случае, если ваш новый тип не полностью покрывается основными полями уведомления. Он также упрощает итерацию по всем уведомлениям.

Благодаря MTI вы получаете экономию памяти и простоту настройки в соответствии с потребностями класса без необходимости переопределять одни и те же столбцы для каждого нового типа уведомления. Только уникальные.

Однако эта схема также имеет главный недостаток STI. Таблица заменит 4. Что может начать вызывать замедление, когда станет огромным.

Короткий ответ: нет, в таком подходе нет необходимости. Я считаю это наиболее СУХИМ способом эффективного решения проблемы. В краткосрочной перспективе STI - это способ сделать это. В долгосрочной перспективе MTI - это правильный путь, но мы говорим о точке, когда вы получаете миллионы уведомлений. Этот подход представляет собой неплохую золотую середину, которую легко расширять.

Подробный гем

Я построил жемчужину над вашим решением: https://github.com/czaks/detailed . С его помощью вы можете упростить свой класс уведомлений до:

class Notification < ActiveRecord::Base
  include Detailed
end

Остальное идет прежним путем.

В качестве дополнительного бонуса теперь вы можете напрямую обращаться (читать, писать, связывать) к атрибутам, зависящим от подкласса: уведомление .phone_number , не прибегая к: notification.details.phone_number . Вы также можете написать весь код в основных классах и подклассах, оставив модель Details пустой. Вы также сможете выполнять меньше запросов (в приведенном выше примере 4 вместо N + 1) для больших наборов данных, используя уведомление .

20
ответ дан 3 December 2019 в 04:13
поделиться
has_one :details, :class_name => "#{self.class.name}Detail"

не работает. self.class.name в контексте определения класса - это 'Class', поэтому: class_name всегда равно 'ClassDetail'

Так должно быть:

has_one :details, :class_name => "#{self.name}Detail"

Но очень хорошая идея!

1
ответ дан 3 December 2019 в 04:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: