在Rails 4中为STI模型生成通用路径

时间:2014-01-21 18:06:11

标签: ruby-on-rails ruby-on-rails-4 sti

假设我有一个管理Widget个对象的Rails 4应用程序,并且使用简单表继承我有专门化Widget::FooWidget::Bar

我想通过一个Widget管理我的所有WidgetsController个对象。

我有以下型号:

class Widget < ActiveRecord::Base; end

class Widget::Foo < Widget
  # Foo specific details...
end

class Widget::Bar < Widget
  # Bar specific details...
end

一个简单的控制器:

class WidgetsController < ApplicationController
  def index
    @widgets = Widget.all
  end

  def show
    @widget = Widget.find(params[:id])
  end
end

我的路线包括

resources :widgets, only: [:index, :show}

在我的index.html.haml我有类似的内容:

- @widgets.each do |widget|
  = link_to "View your widget!", [@widget]

哪一切都出错了。

url_forpolymorphic_path之间,Rails将尝试查找widget_foo_path,而不是使用现存的widget_path

我宁愿不添加其他路由或控制器,我宁愿不手动指定url帮助器。有没有办法告诉Rails Widget::FooWidget::Bar对象应该使用widget_path帮助器链接?

1 个答案:

答案 0 :(得分:0)

我最终通过创建一个mixin解决了这个问题:

module GenericSTIRoutes
  def initialize(klass, namespace = nil, name = nil)
    super(klass, namespace, name)

    superklass = klass

    while superklass.superclass != ActiveRecord::Base
      superklass = superklass.superclass
    end

    @param_key          = _singularize(superklass.name)
    @route_key          = ActiveSupport::Inflector.pluralize(@param_key)
    @singular_route_key = @param_key.dup
    @route_key << "_index" if @plural == @singular
  end
end

然后按如下方式修改Widget.model_name

def self.model_name
  @_model_name ||= Class.new(ActiveModel::Name) do
    include GenericSTIRoutes
  end.new(self, nil)
end