我的网页网址就像'/ about',我的城市网址就像'/ san-francisco'。没有重叠。我怎样才能让以下路线发挥得更好?
get '/:city_slug', :to => 'cities#show', :as => 'city'
get ':action', :controller => "site", :action => 'show'
答案 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
代码中有两件事需要注意:
约束本身由以下类组成:
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
或按国家/地区命名城市(我们/州/等) - 如果您无法区分它们,您无疑会在某些时候遇到重复的城市名称。