StackOverflow似乎有这种问题的路线:
/questions/:id/*slug
在路线和to_param
中都很容易实现。
但是,当只传递一个ID时,StackOverflow似乎也会重定向到该路径。
示例:
stackoverflow.com/questions/6841333
重定向到:
stackoverflow.com/questions/6841333/why-is-subtracting-these-two-times-in-1927-giving-a-strange-result/
与slug的任何变化相同
stackoverflow.com/questions/6841333/some-random-stuff
仍然会重定向到相同的网址。
我的问题是:这种类型的重定向通常是在控制器中处理的(将请求与路由进行比较)还是有办法在routes.rb
中执行此操作?
我不认为routes.rb
文件中存在这种情况的原因是,通常情况下,您无法访问该对象(因此您无法根据ID获取slug,对吧?)
对于任何感兴趣的人,Rails 3.2.13并使用FriendlyID
答案 0 :(得分:3)
好的,所以我想我已经有了这个。
我正在考虑使用中间件做一些事情,但后来决定可能不适合这种类型的功能(因为我们需要访问ActiveRecord)。
所以我最终建立了一个服务对象,称为PathCheck
。该服务如下所示:
class PathCheck
def initialize(model, request)
@model = model
@request = request
end
# Says if we are already where we need to be
# /:id/*slug
def at_proper_path?
@request.fullpath == proper_path
end
# Returns what the proper path is
def proper_path
Rails.application.routes.url_helpers.send(path_name, @model)
end
private
def path_name
return "edit_#{model_lowercase_name}_path" if @request.filtered_parameters["action"] == "edit"
"#{model_lowercase_name}_path"
end
def model_lowercase_name
@model.class.name.underscore
end
end
这很容易实现到我的控制器中:
def show
@post = Post.find params[:post_id] || params[:id]
check_path
end
private
def check_path
path_check = PathCheck.new @post, request
redirect_to path_check.proper_path if !path_check.at_proper_path?
end
我的||
方法中的find
是因为为了保持足智多谋的路线,我做了类似......
resources :posts do
get '*id' => 'posts#show'
end
这将在/posts/:post_id/*id
/posts/:id
的路线
这样,数字ID主要用于查找记录(如果可用)。这样,我们就可以将/posts/12345/not-the-right-slug
松散地匹配,以重定向到/posts/12345/the-right-slug
该服务以通用方式编写,因此我可以在任何资源丰富的控制器中使用它。我还没有办法打破它,但我愿意纠正。
Ryan Bates的 Jared Fine