I am wondering what would be the best way (or indeed any kind of way) to prefix path/url helpers that get generated by Rails?
I.e. I need my dogs_path equivalent of having "extra/path" + dogs_path
I am not looking to namespace my routes (i.e. scope '/admin' { #my_routes }), this is needed specifically to address some reverse proxying issues that I'm having.
Any help would be appreciated!
Why not simply define your route with as option like this?
get 'dogs' => 'dogs#index', as: 'extra_path_dogs'
This will give you:
extra_path_dogs GET /dogs(.:format) dogs#index
And, you can use extra_path_dogs_path afterwards.
Related
I have the following routes in my Rails application:
resources :photos
get "/photos/*id/stats" => "photos#stats"
get "/photos/*id/visitors" => "photos#visitors"
The id parameter is a wildcard that should allow special characters like slashes. Basically, "/photos/img/trial.jpg/stats" should route to stats method in photos_controller with photo id as "img/trial.jpg".
This part is working correctly.
However, I am not sure how to use wildcard matching for id in the default routes created by "resources :tags", which are basic CRUD routes like "/photos/:id/edit" => "photos#edit".
Is there a cleaner way to use wildcard matching for default resource routes, rather than not use resource routes and specify those routes explicitly?
You should be able to do something like
resources :photos
get "/photos/:slug/stats" => "photos#stats"
get "/photos/:slug/visitors" => "photos#visitors"
I am guessing that you are using something like friendy_id
As explained in the Rails guide and the answer above, you'd usually use the colon notation. The guide calls them dynamic segments.
These do however not work as intended in your case, since they don't allow dots by default (dots are reserved for specifying the format of the query). You override the default behavior by specifying your own constraint
get "/photos/:id/stats" => "photos#stats", id: /[^\/]+/
This for example only disallows / in the id. Slashes can not be allowed, since then we would have no way to detect the trailing /stats. You could possibly escape the slashes or replace them in URLs with something. The other answer mentions the friendly id gem, which could be a good way to automate this (I'm not using it, though).
When discussing Routing using Dynamic Segments, the Ruby on Rails Guides (v4.0.1) say "You can't use :namespace or :module with a :controller path segment." They go on to suggest: "if you need to do this then use a constraint on :controller that matches the namespace you require."
I've got a lot of controllers under quite a few namespaces. If I could get dynamic segments to work in my situation then I could handle all of that routing with one line in routes.rb. Perhaps something like this:
get '/:namespace/:controller/:action' #note: this isn't valid
But that won't work (see above). I'd rather keep the namespaces, so I could just write out a fresh line in my routes.rb file for each namespace and then add a constraint to check that the URL is asking for that namespace. That wouldn't be the end of the world. It just seems so un-DRY and a shame because all the routing information is neatly presented right there in the URL.
I'm just wondering if there are any sneaky ways round what seems (to me) like a bit of a gap in the capabilities of Dynamic Segment Routing. Can one get the Routing DSL to run a block that (unlike Constraints) does something more complex than a Boolean yes/no on whether the route matches? Or perhaps I'm missing something in the way the standard Rails routing capabilities work. Any suggestions appreciated.
Update: Just to spell it out a little bit more. My understanding of the Rails Guides is that I'll need to have lines like these:
post ':controller/:action' , controller: /user_details\/[^\/]+/
post ':controller/:action' , controller: /preferences\/[^\/]+/
...and so on. If I want 20 namespaces then I'll need 20 of these lines. I'm just wondering if there isn't a more concise way that approaches my 1-line ideal given above.
If what you want is a dynamic route that matches all routes like
post 'user_details/name/edit' => 'user_details/name#edit'
post 'user_details/address/edit' => 'user_details/address#edit'
post 'user_details/password/edit' => 'user_details/password#edit'
post 'preferences/privacy/edit' => 'preferences/privacy#edit'
post 'preferences/colors/edit' => 'preferences/colors#edit'
then you could just use
post ':controller/:action'
since the :controller part will match namespaced controllers, too.
Verified for Rails 4.0.1 and 4.2.0.
I'm having a little trouble understand how routes work in Ruby on Rails.
What I'm trying to achieve is have all ID's accessible directly after the domain name,
for instance
domain.com/<- ID goes here->
routes to
domain.com/fetch/<- entered ID ->
Any push in the right direction would be greatly appreciated.
Thanks a lot
This might be a bad idea; once you put in this general route then any unrecognized url with a single path component is going to end up being handled by your fetch method. Assuming you understand and are okay with that there are several ways that you could do this, the most straightforward:
I assume that you already have /fetch/:id in your routes, something like this to handle /fetch requests in ApplicationController#fetch:
namespace :fetch
get '/:id' => 'application#fetch'
end
Then you can add a rule at the bottom of your routes like this:
get '/:id' => 'application#fetch'
That should go at the very bottom because you don't want it to override any more specific single-path-component routes.
Since the beginning I always hat this one problem with rails, short urls without the controller name.
For example, I have a blog and I don't want any dates or controller names in the url, I already have a Page model with a unique field url in my database. Rails works great with such urls:
jeena.net/pages/1
And when I modify the model I even can get it to use
jeena.net/pages/foo
But it seems not to matter what I do I can not get it to work with just:
jeena.net/foo
Of course I want the index page still to work with
jeena.net/pages
And I want creating new pages and updating old pages to work too in some was as well as the link_to()-method. All suggestions are appreciated.
To define that route, try adding the following to your routes.rb:
match '/:id' => 'your_controller#your_action'
This will pretty much match everything to the id of your model. And that's not very nice... You don't want to route youe_host/pages to the pages controller, with an id equal to 'pages'... To prevent that from happening, make sure to put that line on the end of the routes.rb file. The router uses the first route that matches the path received, so putting that line on the end of it will make sure that it will only match your route after it ran out of other meaningful options.
A better practice would be to pass regexp constraints to the router, so that it will only match ids with a specific format, like that:
match '/:id' => 'your_controller#your_action', :constraints => { :id => /your_regexp/ }
Refer to the guides if you have doubts about the rails rounting system. It is pretty well written and covers lots of important things.
Rails rounting - Official Guides
edit: to create a named route, one that you can call in your controllers and override the normal routes that you are probably creating with resource, you have to provide the :as => parameter in your routes.rb
match '/:id' => 'your_controller#your_action', :as => some_name
Then you'll be able to call it in your controller/views like this:
link_to some_name_path(#my_string_id)
Hope this helps. And take a time to read the guides, it has really lots of useful info, including more details about creating named routes.
I have the following route:
get "/:user_name/things/:thing_name" => "things#show", :as => "show_user_thing"
Thing belongs to user. So with just an instance of thing I have both parameters. However, when using the route helpers, I'm forced to specify each segment separately like so:
show_user_thing_path(#thing.user, #thing)
This sucks. I'd much rather do just this:
show_user_thing_path(#thing)
But how do I do this the 'route helper way'? I'd love to still use all the rails goodies for route's like these. Any ideas?
I feel your pain. In the cases where I uses the url helper a lot, I just write my own helper.
def show_thing_by_user_path(thing)
show_user_thing_path(thing.user, thing)
end
Of course you'd have to modify it slightly to include any options and formatting, but I think you get the idea of what I'm saying.