设置路由以允许将额外的路径元素(一个slug)传递给Rails 3中的URL的正确方法是什么。我想不要打破一些你用show和new获得的魔法当您将对象列为资源时。
这是一个例子:
http://somewebserver.com/topics/1/learning-rails
但我仍然希望这个工作
http://somewebserver.com/topics/1
这些
http://somewebserver.com/topics/new
http://somewebserver.com/topics/1/edit
答案 0 :(得分:1)
虽然最好让你的slugs看起来像“1-learning-rails”,因为Rails 3现在allows the use of Rack applications来处理路由,所以你可以这样做:
# lib/topic_slugger.rb
class TopicSlugger
AD_KEY = "action_dispatch.request.path_parameters"
def self.call(env)
controller = (env["PATH_INFO"].split("/")[1].camelize+"Controller").constantize
glob = env[AD_KEY][:glob]
slug, action_name = nil
if glob
path_params = glob.split("/")
if path_params.length == 1
if ["new","edit"].include?(path_params.first)
# no slug present
action_name = path_params.first
else
slug = path_params.first
end
else
action_name = path_params.first
slug = path_params.last
end
end
env[AD_KEY][:slug] = slug if slug
action = if action_name # "new" or "edit"
action_name.to_sym
else
case env["REQUEST_METHOD"]
when "PUT" then :update
when "DELETE" then :destroy
else :show
end
end
controller.action(action).call(env)
end
end
# config/routes.rb
require 'topic_slugger'
Ztest::Application.routes.draw do
# handle show, new, edit, update, destroy
match 'topics/:id/*glob' => TopicSlugger
# handle index, create
resources :topics
end
这会接受"/topics/1/foo/bar"
形式的请求,并将它们传递给TopicSlugger Rack应用程序,该应用程序决定glob是否包含组合动作/ slug(如"new/learning-rails"
),或只是一个slug({{ 1)}),将slug添加到环境的请求参数中,然后将环境传递给控制器操作,控制器操作本身就是一个Rack应用程序。 “index”和“create”通常由"learning-rails"
语句处理。
因此,例如,resources
将使用"GET /topics/1/new/learning-rails"
TopicsController#new
答案 1 :(得分:0)
由于/
被视为路径分隔符,因此Rails建议您使用更“中立”的slug
将ID与-
分开。
请参阅this screencast。
否则,您需要传递自定义:id
验证,并让Rails知道:id
可以包含/
,但事情并非那么简单。