Решение has_many_polymorphs, о котором вы упоминаете, не так уж и плохо.
class Task < ActiveRecord::Base
has_many_polymorphs :targets, :from => [:store, :software, :office, :vehicle]
end
Кажется, делает все, что вы хотите.
Предоставляет следующие методы:
к заданию:
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
на программное обеспечение, магазин, офис, транспортное средство:
s = Software.first # works for any of the subtargets.
s.tasks # lists tasks associated with s
Если я правильно слежу за комментариями, единственной оставшейся проблемой является то, что вам не нужно изменять app / models / task.rb каждый раз, когда вы создаете новый тип Subtarget. Путь Rails, кажется, требует, чтобы вы изменили два файла для создания двунаправленной ассоциации. has_many_polymorphs требует только, чтобы вы изменили файл Tasks. Похоже, победа для меня. Или, по крайней мере, так было бы, если бы вам не пришлось редактировать новый файл модели.
Есть несколько способов обойти это, но они кажутся слишком много работы, чтобы избежать изменения одного файла время от времени. Но если вы настроены против изменения Task самостоятельно, чтобы добавить к полиморфным отношениям, вот мое предложение:
Храните список подзадач, я собираюсь предложить в lib / subtargets отформатировать одну запись на строку, которая по сути является table_name.underscore. (Заглавные буквы имеют префикс подчеркивания, а затем все делается строчными)
store
software
office
vehicle
Создайте config / initializer / 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
И это автоматически обновит ваш полиморфный список, как только вы перезагрузите консоль или перезапустите рабочий сервер.
Как я уже сказал, очень много работы по автоматическому обновлению списка подзадач. Однако, если вы пойдете по этому пути, вы можете настроить собственный генератор, чтобы убедиться, что все необходимые части модели подзадачи присутствуют при его создании.