Наследование и маршрутизация в одной таблице в Ruby on Rails 3.0 - PullRequest
4 голосов
/ 19 апреля 2011

У меня возникли проблемы с настройкой маршрутизации для удобного использования Single Table Inheritance в моем приложении Ruby on Rails. Я использую Ruby 1.9.2 и Rails 3.0.6. Он находится в разработке, поэтому серверная часть - это SQLite3, на случай, если что-то изменится.

Допустим, у меня есть два продукта, widgets и sprockets. Мое приложение отслеживает номера ошибок и заявки на поддержку для обоих продуктов, но сами ошибки и заявки на поддержку хранятся в других системах. Над этими двумя продуктами работают две отдельные команды.

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

Команда виджетов заботится только об информации виджетов, а команда звездочек заботится только об информации звездочек. Есть третья команда, которая должна иметь возможность просматривать информацию как на виджетах, так и на звездочках. Команда виджетов получит доступ к приложению по пути /widgets, а команда звездочек получит доступ к приложению по пути /sprockets. Я настроил это в routes.rb, используя пространства имен:

resources :bugs

namespace "widgets" do
  resources :bugs
end

namespace "sprockets" do
  resources :bugs
end

Я настроил следующие модели, которые работают, как и ожидалось, когда я запускаю irb и использую WidgetBug.create() или SprocketBug.create():

bug.rb

class Bug < ActiveRecord::Base
end

widget_bug.rb

class WidgetBug < Bug
  # Some validation rules
end

sprocket_bug.rb

class SprocketBug < Bug
  # Some different validation rules
end

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

  def index
    # The scaffold code lists all bugs, which is not what we want
    # @bugs = Bug.all

    # Only return bugs of the subclass we're looking for
    @bugs = eval("#{params[:controller].classify}.all")

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @bugs }
    end
  end

Затем я использовал create(), чтобы заполнить базу данных несколькими ошибками каждого типа. К сожалению, когда я перехожу к /widgets/bugs, появляются ошибки для обоих продуктов. После некоторой отладки я определил, что вызов classify возвращает Widgets::Bugs или Sprockets::Bugs, поэтому, когда я вызываю все на нем, он работает против суперкласса, а не против подкласса.

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

Ответы [ 2 ]

4 голосов
/ 19 апреля 2011

Оформить заказ: STI, один контроллер

Маршруты

resources :widgets, :controller => "bugs", :type => "Widget"
resources :sprockets, :controller => "bugs", :type => "Sprocket"
# And I don't know if you need this
resources :bugs, :type => "Bug"

Контроллер

def index
  @bugs = params[:type].constantize.all
end

UPD

namespace "widgets" do
  resources :bugs, :type => "Widget"
end

namespace "sprockets" do
  resources :bugs, :type => "Sprocket"
end
0 голосов
/ 26 апреля 2013

Я написал сообщение в блоге о STI в Rails 3, в котором обсуждаются некоторые распространенные подводные камни и правильные обходные пути, включая проблему, о которой вы упомянули.http://www.christopherbloom.com/2012/02/01/notes-on-sti-in-rails-3-0/

...