奇怪的路由

时间:2010-06-15 20:57:44

标签: ruby-on-rails seo url-routing friendly-url

如何设置我的rails应用以响应此类网址:

http://mydomain.com/white-halogene-lamp

http://mydomain.com/children-lamps

http://mydomain.com/contact-form

第一个应链接到我的产品控制器,并以此名称显示我的产品

第二个应链接到我的类别控制器,并显示具有此名称的类别

第三个应链接到我的网站控制器,并显示具有此标题的网站。

所有三个模型(产品,类别,网站)都有一个方法to_seo,给出上面提到的网址(在斜线之后)

我知道这不是宁静的方式,但请不要在这里讨论,这是不对的方法,不是问题。

问题是如何完成这种奇怪的路由?

我知道我们已经捕获了所有路由,但是如何告诉rails在catch all路由中的不同url上使用不同的控制器?或者你有更好的主意吗?

我会避免重定向到其他网址。

4 个答案:

答案 0 :(得分:3)

这有点奇怪,特别是如果重定向是不可能的,但实现这种需求的一种方法可能是从表中填充路由映射 - routes.rb只是另一段ruby代码,所以如果你能放

map.connect 'children-lamps', :controller => 'category', :action => 'show',  :id => 123

或者你在routes.rb中定义它的其他方式,那么你也可以把

Category.each { |category|
  map.connect category.to_seo, :controller => 'category', :action => 'show', :id => category.id
}

但是,只有当您的类别/网站是静态的时,这才有用。

答案 1 :(得分:1)

最好的方法是添加另一个图层,然后像这样运行路径:

http://yoursite.com/products/white-halogene-lamp

因为这可以通过以下方式完成:

map.product_seo "prodcuts/:product", :controller => :products, :action => :show

然后在产品#中将更改@product=Product.find(params[:id])显示为:

@product=Product.find_by_name(params[:product]) if params[:product] #This assumes name is the field you are searching on
@product=Product.find(params[:id]) unless params[:product]

这样旧的路线仍然有效,但你也可以获得SEO网址。

对于类别,只需根据需要重复和更改(url将是/ categorys / children-lamps)

对于网站控制器,你真的需要相同的东西,没有顶层说你想要你必须手动定义每条路线

答案 2 :(得分:0)

您可以使用路线约束。

class ProductExistsConstraint

  def matches?(request)
    Product.exists? :slug => request.path_parameters['slug']
  end

end

和类别和页面的类似类。然后在路线

match ":slug" => "products#show", :constraints => ProductExistsConstraint.new
match ":slug" => "categories#show", :constraints => CategoryExistsConstraint.new
match ":slug" => "page#show", :constraints => PageExistsConstraint.new

我没有对此进行测试,但我认为这至少是指向正确方向的指针。另见:http://guides.rails.info/routing.html#advanced-constraints

答案 3 :(得分:0)

我必须做一些非常相似的事情。您可以简单地设置这样的通用句柄操作:

def handle
  @product = Product.find_by_permalink params[:permalink]
  if product
    return render_product
  end

  @category - Category.find_by_permalink
  ..
end

private

def render_product
  # something like this.
  render :file => 'products/show'
end