Наследование и маршрутизация одной таблицы в Ruby on Rails 3.0

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

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

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

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

resources :bugs

namespace "widgets" do
  resources :bugs
end

namespace "sprockets" do
  resources :bugs
end

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

ошибка.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

Я использовал скаффолдинг для создания контроллера и представления для объекта ошибки, затем изменил контроллер, чтобы попытаться обобщить его, чтобы его можно было использовать как с ошибками виджетов, так и с ошибками звездочек. Например, метод 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, но я все еще не понимаю, как я могу изменить маршрутизацию или контроллер, чтобы все работало правильно. Любая помощь будет принята с благодарностью.


person Ion the Geek    schedule 19.04.2011    source источник
comment
проверить этот пост stackoverflow.com/q/5246767/298624   -  person fl00r    schedule 19.04.2011


Ответы (2)


Ознакомьтесь с этим сообщением: 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
person fl00r    schedule 19.04.2011
comment
Это очень близко к тому, что я ищу, но не совсем точно. Это позволяет мне получить доступ к ошибкам виджетов под /widgets, но я хочу получить доступ к ошибкам виджетов под /widgets/bugs. Это возможно? - person Ion the Geek; 20.04.2011
comment
Выдающийся! Спасибо! Когда я регенерировал код с нуля, я обнаружил одно важное предостережение: ДОЛЖЕН быть пустой каталог с именем widgets в каталоге контроллеров, иначе посещение /widgets/bugs завершится ошибкой с ошибкой маршрутизации неинициализированными постоянными виджетами. - person Ion the Geek; 20.04.2011
comment
Это очень странный баг, я даже представить не могу :) - person fl00r; 20.04.2011
comment
Два года спустя, но я нашел это через Google, поэтому: Не используйте константу для строк, вводимых пользователем!. Таким образом все виды зла могут проникнуть в остальную часть вашего кода. Создайте хотя бы белый список. - person phillmv; 17.07.2013

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

person Chris Bloom    schedule 26.04.2013