Ruby on Rails 3:同一命名空间中的多个路由

时间:2010-09-28 04:43:31

标签: ruby-on-rails

我的网页网址就像'/ about',我的城市网址就像'/ san-francisco'。没有重叠。我怎样才能让以下路线发挥得更好?

get '/:city_slug', :to => 'cities#show', :as => 'city'
get ':action', :controller => "site", :action => 'show'

3 个答案:

答案 0 :(得分:1)

你无法通过直接路由来做到这一点。您可以通过定义当无法找到City然后重定向到站点控制器的显示页面,并通过页面名称来解决此问题。在路线中需要这样的东西:

get ':slug', :to => "cities#show", :as => "city"
get ':page', :to => "site#show", :as => "page"

show的{​​{1}}操作中,您可以执行查找,然后在引发ActiveRecord :: RecordNotFound时从中进行救援。

CitiesController

或者您知道,您可以为每个网页定义路线并停止此重定向malarky。

def show
  @city = City.find_by_slug!(params[:slug])
  rescue ActiveRecord::RecordNotFound
    redirect_to(page_path(params[:slug])
end

答案 1 :(得分:1)

我非常不同意@ ryan的答案中的“重定向”部分。它会使您的服务器通信加倍 - 它会起作用,但它绝对不是一个好的解决方案。重新排序的想法是完全正确的。

所以有我的解决方案 - 我真的不确定它是否可以,但它似乎以某种方式工作。

在您的routes.rb中:

get ":slug", :to => "cities#show", :constraints => CityConstraint.new, :as => city
get ":slug", :to => "site#show", :as => page

代码中有两件事需要注意:

  • :slug 在第二种情况下 - 这很奇怪,但必须以与第一种方式相同的方式命名。我无法管理它:在您的情况下页面。但我认为这不是什么大不了的事。
  • :约束 - 这是正常的documented

约束本身由以下类组成:

class CityConstraint
  def matches?(request)
    # The condition would normally go through ActiveRecord to test the 
    # existence of town dynamically
    towns = %w(london prague washington)
    towns.include?(request.params[:slug])
  end
end

每当有约束的规则的路由表中有命中时,约束就会运行(方法匹配?)。我相信这就是你所需要的。可能某种形式的缓存不会破坏性能。

顺便说一下 - 这个解决方案只是理论上的,我从未在生产中使用它。如果有人会测试它会很棒: - )

答案 2 :(得分:0)

  

我的网页网址就像'/ about',我的城市网址就像'/ san-francisco'。

如果你没有对两种不同类型的对象的网址进行命名空间,就没有办法区分它们,没有对db(昂贵的)或硬编码的城市/页面列表进行额外检查(脆弱)每次您收到您网站上任何页面/城市的请求。

如果您可以命名网址,那么这是更好的方法 - 所以要么:

cities/san-fransisco

pages/about

取决于您认为最重要的是保持在根级别。如果还有/ cities页面,那么您的用户自然会将其保留在该页面之下,这样他们就可以轻松地向上移动到城市页面并查看网址之间的关系,并让您稍后显示城市/顶部等等。路线很明显

get "cities/:slug", :to => "cities#show", :as => city
get ":slug", :to => "site#show", :as => page

并避免任何冲突问题。

如果您必须将城市保持在根级别,则可以将页面放在/ pages下,并将城市作为根级别。否则你就会在决定路线时做更多的工作(每次路线进入时都会查找)。

你可以考虑的另一件事是向城市添加数字ID,这也有助于你处理冲突的名字(在美国很常见,在整个世界非常普遍),所以你有

/1-san-francisco
/2-san-francisco (San Francisco, Minnesota)

和路线:

get ":slug", :to => "cities#show", :as => city, :constraints => { :slug => /\d*-[\w]*/ }
get ":slug", :to => "site#show", :as => page

或按国家/地区命名城市(我们/州/等) - 如果您无法区分它们,您无疑会在某些时候遇到重复的城市名称。