Rails:基于请求(和基于数据库)的路由

时间:2013-01-24 19:38:01

标签: ruby-on-rails database routing request multi-tenant

我正在尝试摆脱我目前在我的应用中使用的一些范围前缀。

目前我的路线看起来像这样(简化示例):

scope 'p'
  get ':product_slug', as: :product
end
scope 't' do
  get ':text_slug', as: :text
end

例如生成这些路径:

/p/car
/t/hello-world

现在我希望路径在没有前缀字母(p& t)的情况下工作。所以我将slug限制为现有的数据库条目(顺便说一句,这很棒):

text_slugs = Text.all.map(&:slug)
get ':text_slug', as: :text, text_slug: Regexp.new( "(#{text_slugs.join('|')})"

product_slugs = Product.all.map(&:slug)
get ':product_slug', as: :product, product_slug: Regexp.new( "(#{product_slugs.join('|')})"

问题:

这是一个多租户应用,这意味着某些人text_slug可能是另一个product_slug,反之亦然。这就是为什么我必须通过当前站点(按域)过滤slu ..

解决方案如下所示:

text_slugs = Site.find_by_domain(request.host).texts.all.map(&:slug)
get ':text_slug', as: :text, text_slug: Regexp.new( "(#{text_slugs.join('|')})"

请求在routes.rb中不可用,我尝试的所有内容都无效。

对Rack :: Request的直接调用需要正确的env变量,它在Application.routes中似乎不存在,否则这可能有效:

req = Rack::Request.new(env)
req.host

我真的尝试了很多,感谢任何提示!

1 个答案:

答案 0 :(得分:1)

您可以对此使用高级约束:http://guides.rubyonrails.org/routing.html#advanced-constraints

class SlugConstraint
  def initialize(type)
    @type = type
  end
  def matches?(request)
    # Find users subdomain and look for matching text_slugs - return true or false
  end
end

App::Application.routes.draw do
  match :product_slug => "products#index", :constraints => SlugConstraint.new(:product)
  match :tag_slug => "tags#index", :constraints => SlugConstraint.new(:tag)
end
BTW - 您可能会遇到测试问题,但这是另一个问题......