How to pass params to a block in Rails routes?
I am using Rails 3. And I'm wondering how to pass params to some blocks in routes.rb
.
What I'm trying to do is to make a catch all
route, that check from slugs
database the model name of it by the id.
After getting the model name
i pluralize it to get the controller name.
match '/:id', :controller => proc { Slug.find_by_iid(params[:id]).model.pluralize }, :action => :show
The table slugs
model iid
----- -----
post 4d2c7de0c5abe7f8a9000007
item 4d2c7de0c5abe7f809000004
When I try to access some pages like /4d2c7de0c5abe7f8a9000007
I got this e开发者_StackOverflowrror:
Started GET "/4d2c7de0c5abe7f8a9000007" for
127.0.0.1 at 2011-01-12 00:04:31 +0200
ActionController::RoutingError (wrong constant name #<Proc:0x0000010337c310@):
Rendered /Users/amr/.rvm/gems/ruby-1.9.2-p136@rails3/gems/actionpack-3.0.3/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.2ms)
The expected is to point to posts#view with iid: 4d2c7de0c5abe7f8a9000007
proc
returns a Proc, but match
is expecting a string. You could try adding .call
to have the proc return its value. Though I'm not sure if this will end up calling the proc each time or only when routes
is loaded...
EDIT
Seems I was way off-base with my earlier response and comments. Maybe something like this?:
match '/:id', :to => proc { |env|
id = env["action_dispatch.request.path_parameters"][:id]
model = Slug.find_by_iid(id).model
controller = [model.pluralize.camelize,"Controller"].join.constantize
controller.action("show").call(env)
}
Though this really ought to be defined in a library and included. Perhaps someone knows a better way?
Putting this in your routes seems really hacky. I would recommend creating a Slugs controller, passing this task onto that, and redirecting to the appropriate controller from there. Assuming your other pages use standard RESTful routes, you could do something like this:
Change route to this:
match '/:id', :controller => :slugs, :action => :show
Slugs controller:
def show
slug = Slug.find_by_iid(params[:id])
redirect_to send("#{slug.model}_url", params[:id])
end
精彩评论