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/
对于蛞蝓的任何变体也是如此
stackoverflow.com/questions/6841333/some-random-stuff
仍会重定向到相同的 URL。
我的问题是:这种类型的重定向通常是在 Controller 中处理(将请求与路由进行比较)还是有办法在routes.rb
中执行此操作?
我认为在 routes.rb
文件中不可能出现这种情况的原因是,通常您无权访问该对象(因此您无法根据ID,对吗?)
对于任何感兴趣的人,Rails 3.2.13 以及还使用 FriendlyID
最佳答案
好的,我想我已经明白了。
我正在考虑使用中间件做一些事情,但后来决定这可能不适合这种类型的功能(因为我们需要访问 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
这很容易实现到我的 Controller 中:
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/:id
之上创建如下路由:/posts/:post_id/*id
这样,数字 ID 主要用于查找记录(如果有)。这允许我们松散匹配 /posts/12345/not-the-right-slug
以重定向到 /posts/12345/the-right-slug
该服务是以通用方式编写的,因此我可以在任何资源丰富的 Controller 中使用它。我还没有找到打破它的方法,但我愿意接受纠正。
资源
Railscast #398: Service Objects by Ryan Bates
This Helpful Tweet by Jared Fine
关于ruby-on-rails - 带有智能重定向的 StackOverflow 风格路由,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16654671/