Хотя, вероятно, лучше, чтобы ваши слагы выглядели как "1-learning-rails", поскольку Rails 3 теперь позволяет использовать приложения Rack для обработки маршрутов, так что вы можете сделать что-то вроде этого:
# 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, которое решает, содержит ли глобус комбинация action / slug (например, "new/learning-rails"
), или просто slug ("learning-rails"
), добавляет слаг к параметрам запроса среды, затем передает среду действию контроллера, которое само является приложением Rack.«index» и «create» обычно обрабатываются оператором resources
.
Так, например, "GET /topics/1/new/learning-rails"
будет отправлен в TopicsController#new
с хэшем params { :id => "1", :slug => "learning-rails, :glob => "new/learning-rails" }