Направляющие: Многие ко многим полиморфным отношениям

Я думаю, что Вы не должны рассматривать определенную реализацию синтаксического анализатора. API Java для обработки XML позволяет Вам использовать любую реализацию синтаксического анализатора приспосабливания стандартным способом. Код должен быть намного более портативным, и когда Вы понимаете, что определенный синтаксический анализатор стал слишком старым, можно заменить его другим, не изменяя строку кода (если Вы делаете это правильно).

В основном существует три способа обработать XML стандартным способом:

  • SAX Это - самый простой API. Вы читаете XML путем определения класса Обработчика, который получает данные в элементах/атрибутах, когда XML обрабатывается последовательным способом. Это быстрее и более просто, если Вы только планируете считать некоторые атрибуты/элементы и/или записать некоторые значения обратно (Ваш случай).
  • DOM Этот метод создает дерево объектов, которое позволяет Вам изменить/получить доступ его случайным образом, таким образом, это лучше для сложного управления XML и обработки.
  • StAX Это посреди пути между SAX и DOM. Вы просто пишете код для получения по запросу данных из синтаксического анализатора, Вы интересуетесь тем, когда это обрабатывается.

Забывают о собственных API, таких как JDOM или Apache (т.е. Apache Xerces XMLSerializer), потому что свяжет Вас с определенной реализацией, которая может развиться вовремя или потерять назад совместимость, которая заставит Вас изменить свой код в будущем, когда Вы захотите обновить до новой версии JDOM или безотносительно синтаксического анализатора, Вы используете. Если Вы будете придерживаться API стандарта Java (использующий фабрики и интерфейсы), то Ваш код будет намного более модульным и удобным в сопровождении.

нет никакой потребности сказать, что все (я не проверил все, но я почти уверен) предложенных синтаксических анализаторов, выполняют реализацию JAXP так технически, можно использовать все, неважно, который.

33
задан Alexander Trauzzi 15 July 2009 в 19:18
поделиться

5 ответов

Возможно, это не особенно полезный ответ, но, говоря просто, я не думаю, что есть простой или автоматический способ сделать это. По крайней мере, не так просто, как с более простыми ассоциациями «к одному» или «ко многим».

Я думаю, что создание модели ActiveRecord для таблицы соединений - верный путь решения проблемы. Нормальное отношение has_and_belongs_to_many предполагает соединение между двумя указанными таблицами, тогда как в вашем случае это звучит так, как будто вы хотите соединиться между задачами и любым из хранилищ , программное обеспечение , офисы или автомобили (кстати, есть ли причина не использовать здесь STI? Похоже, это поможет уменьшить сложность, ограничив количество таблиц у вас есть). Итак, в вашем случае таблица соединения также должна знать имя задействованного подкласса Target . Что-то вроде

create_table :targets_tasks do |t|
  t.integer :target_id
  t.string :target_type
  t.integer :task_id
end

Затем в своем классе Task , подклассах Target и классе TargetsTask вы можете настроить has_many ассоциации с использованием ключевого слова : through , как описано на страницах rdoc ActiveRecord :: Associations :: ClassMethods .

Но, тем не менее, это лишь часть пути, потому что : через не будет знать, как использовать поле target_type в качестве имени подкласса Target . Для этого вы могли бы написать несколько пользовательских SQL-фрагментов select / finder, также описанных в ActiveRecord :: Associations :: ClassMethods .

Надеюсь, это поможет вам двигаться в правильном направлении.

0
ответ дан 27 November 2019 в 18:02
поделиться

Я согласен с остальными. Я бы выбрал решение, использующее сочетание STI и делегирования, которое было бы намного проще реализовать.

Суть вашей проблемы - где хранить записи всех подклассов Target. ActiveRecord выбирает базу данных через модель STI.

Вы можете сохранить их в переменной класса в Target и использовать унаследованный обратный вызов для добавления к нему новых. Затем вы можете динамически сгенерировать нужный вам код из содержимого этого массива и использовать method_missing.

0
ответ дан 27 November 2019 в 18:02
поделиться

Применяли ли вы метод грубой силы:

class Task 
  has_many :stores
  has_many :softwares
  has_many :offices
  has_many :vehicles

  def targets
    stores + softwares + offices + vehicles
  end
  ...

Возможно, он не такой элегантный, но, честно говоря, он не такой многословный, и в коде нет ничего изначально неэффективного.

0
ответ дан 27 November 2019 в 18:02
поделиться

Вы можете комбинировать полиморфизм и has_many: через , чтобы получить гибкое отображение:

class Assignment < ActiveRecord::Base
  belongs_to :task
  belongs_to :target, :polymorphic => true
end

class Task < ActiveRecord::Base
  has_many :targets, :through => :assignment
end

class Store < ActiveRecord::Base
  has_many :tasks, :through => :assignment, :as => :target
end

class Vehicle < ActiveRecord::Base
  has_many :tasks, :through => :assignment, :as => :target
end

... И так далее.

56
ответ дан 27 November 2019 в 18:02
поделиться

Упомянутое вами решение has_many_polymorphs не так уж и плохо.

class Task < ActiveRecord::Base
  has_many_polymorphs :targets, :from => [:store, :software, :office, :vehicle]
end

Кажется, делает все, что вы хотите.

Оно предоставляет следующие методы:

to Task:

t = Task.first
t.targets   # Mixed collection of all targets associated with task t
t.stores    # Collection of stores associated with task t
t.softwares # same but for software
t.offices   # same but for office
t.vehicles  # same but for vehicles

to Программное обеспечение, магазин, офис, транспортное средство:

s = Software.first    # works for any of the subtargets.
s.tasks               # lists tasks associated with s

Если я правильно слежу за комментариями, единственная оставшаяся проблема заключается в том, что вам не нужно изменять app / models / task.rb каждый раз, когда вы создаете новый тип Подцель. Похоже, что способ Rails требует от вас изменения двух файлов для создания двунаправленной ассоциации. has_many_polymorphs требует только изменения файла задач. Мне кажется, это победа. Или, по крайней мере, это было бы, если бы вам все равно не приходилось редактировать новый файл модели.

Есть несколько способов обойти это, но они кажутся слишком трудоемкими, чтобы избежать изменения одного файла время от времени. Но если ты' Если вы решительно настроены против изменения задачи самостоятельно, чтобы добавить к полиморфным отношениям, вот мое предложение:

Сохраните список подцелей, я собираюсь предложить в lib / subtargets отформатировать одну запись на строку, которая по сути является table_name.underscore . (Заглавные буквы имеют префикс подчеркивания, а затем все делается в нижнем регистре)

store
software
office
vehicle

Создайте config / initializers / subtargets.rb и заполните его следующим образом:

SubtargetList = File.open("#{RAILS_ROOT}/lib/subtargets").read.split.reject(&:match(/#/)).map(&:to_sym)

Затем вы захотите создать собственный генератор или новый грабли задачи. Для создания вашей новой подцели и добавления имени модели в файл списка подцелей, определенный выше. Вы, вероятно, в конечном итоге сделаете что-то голое, что внесет изменения и передаст аргументы стандартному генератору.

Извините, мне действительно не хочется проводить вас через это прямо сейчас, но вот некоторые ресурсы

Наконец, замените список в объявлении has_many_polymorphs на SubtargetList

class Task < ActiveRecord::Base
  has_many_polymorphs :targets, :from => SubtargetList
end

С этого момента вы можете добавить новую подцель с

$ script/generate subtarget_model home

, и это автоматически обновит ваш полиморфный список один раз вы перезагружаете консоль или перезапускаете производственный сервер.

Как я уже сказал, автоматическое обновление списка подцелей - это большая работа. Однако, если вы пойдете по этому пути, вы можете настроить настраиваемый генератор, чтобы все необходимые части модели подцели присутствовали при ее создании.

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

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

1
ответ дан 27 November 2019 в 18:02
поделиться
Другие вопросы по тегам:

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