rails controller action routing - ruby-on-rails

I'm looking to "automatically" generate routes based on actions defined in a controller. resources routing (as far as I know) only automatically generates routes & helpers for http verbs. In this instance I'm serving mostly static pages using rails and have no need for http verbs in my controller.
Specifically:
In a controller I have defined actions which refer to those mostly static pages.
def action
end
In the routes file I have a bunch of
match "/url" => 'controller#action'
I'd like all those matched routes to be generated automatically based on the actions in the controller. Something CONCEPTUALLY along the lines of:
for actions in controller.erb do |action|
'match "/action" => "controller#action"
end
Is this possible? Would I write the code in the routes file directly?
I also have some nested actions to consider... a controller action may be:
def action
def nested_action
end
end
I'd appreciate any thoughts on this matter. Thanks.

What's wrong with the normal /:controller/:action idea?
That won't deal with nested actions, but... I'm having a difficult time understanding why you'd ever want that.

You can do something like this:
controller :controller_name do
get "path/action" => :method_name, :as => :path_action
post "path/save" => :method_name, :as => :path_save
end
That is, you can group different routes within a controller using the method above.

Related

Rails Routing: Set specific controller action to a different path

I am looking to set the show action for a controller to a specific path (a path without the controller prefix). I know this can be done by controller by doing this
resources :items, path: ''
But is there a way to do this on only one specific action within the controller?
My end goal is to be able to say www.example.com/my-item-name and take the user to the item without changing the URL. I tried using a catchall route but redirecting adds the prefix back which I do not want.
Any ideas?
You can specify which controller and action respond to a certain route in your routes.rb file, like this:
get 'something', to: 'controller_name#action_name'
See Rails Routing Guide.
You can define single routes manually with the match, get,post, put, macros:
get :bar, to: 'foos#bar'
get :bar, controller: 'foos' # works the same as above
post :bar, to: 'foos#bar'
You can also use scope if you want to route multiple routes to the same controller more elegantly:
scope controller: 'foos' do
get :bar
get :baz
end

Route to /post/new instead of /posts/new in rails?

This is related to a question I asked here: undefined method `posts_path' for #<#<Class:0x007fe3547d97d8>:0x007fe3546d58f0>
I was told to switch my controllers, view etc from "post" to "posts" which fixed the issue, however if I did want to use the URL /post/new, how would I do that without receiving the "undefined method `posts_path'" error I was before?
I don't understand why it's looking for "posts_path" when my controller, model and view are all called "post".
Add this before resources :posts line/block in routes.rb file,
get '/post/new', to: 'posts#new'
When you define routes using resources :posts, by default the route to the new action is /posts/new, So to override the same you need to define custom route like I did above. Also, to search the routes, Rails scans the routes.rb file from top to bottom, whatever matches first is taken. Therefore, to override the default behaviour, I asked you to define this custom route before the default routes.
Hope that helps!
I would suggest that you take a look at Rails Routing Guide.
In short:
Because the model Post describes only one record, it makes sence to call the model Post and not Posts.
With resources :posts within your routes.rb you define that you will have multiple Post objects and you want to expose all CRUD actions with a restfull interface through your controller. Your controller is named PostsController that too makes sence, because your controller provides CRUD actions for all Post objects not only one.
Furthor more rails generate some helpers for every defined route:
posts_(path|url) returns /posts=> shows multiple posts => plural helper name
new_post_(path|url) returns /posts/new => show one post for edit => singular helper name
edit_post_(path|url)(:id) returns /posts/:id/edit => edit one post => singular helper name
photo_(path|url)(:id) => show one post => singular helper name
The route name is always plural because you are always changing the resources. For instance add a new post to the posts resources.
You can also define a singleton resource via resource :geocoder in this case you say you only have one of this thing. For singletons helpers and routes are slightly different. But I saw it until now only rarely.

Rails Routes: How to match Rails routes based on a pattern

I have some routes like:
get 'route1' => 'controller#route1', as: 'route1'
get 'route2' => 'controller#route2', as: 'route2'
get 'route3' => 'controller#route3', as: 'route3'
How can I match more routes automatically with this pattern, e.g. 4, 5...
I am not sure how you can handle as part of route. But you can write this code in another way. You can create a route that handle all such routes at the end of your primary route as below:
get '/:route' => 'controller#route_for_all_views'
In your controller you should have this route_for_all_views action, which can handle all pages.
class SomeController < ApplicationController
def route_for_all_views
# handle your views and code with params[:route] here
end
end
I think you can do something like this:
get "/:action", to: "controller", constraints: {action: /route\d+/}
Please see dynamic segments for routes.
(also note that this would raise an exception if your controller doesn't have the method so you might need to use something like method_missing)
This may be a messy solution, but you could also do something like this, which will give you the *_path and *_url url helpers, that you get when you use the :as option.
%w{ route1 route2 route3 route4 route5 }.each do |route|
get route, to: "controller##{route}", as: route
end

I want the following urls pattern, please help I'm using rails 3

I want the following urls for my UserController:
localhost/user/join
localhost/user/login
localhost/user/user_name (this can be any name in here, it should fire the 'profile' action)
Then within the /user/user_name_here/ folder I want:
/user/user_name/blah1/
/user/user_name/blah2/
/user/user_name/blah3/
It seems doing resources :user only creates things for index/show/get, so I'm confused as to how to do this other than creating so many match '/user/join' etc. lines in routes.
match "user/:user_name" => "users#show"
then /user/username will redirect to the User controller, call the show method, and pass the :user_name param
you could do the same to other actions that doesn't neet parameters,
match '/user/login' => "sessions#new"
match '/user/join' => "user#new"
Yup - 'resources :user' is just scaffolding for the usual CRUD methods. If you want paths additional to those, you're going to have to create routes (it's the only way your app knows how to route a given URL to a given controller and method).
The friendly_id gem does something similar to what you're suggesting (though I believe it's monkey-patching the .find method on ActiveRecords classes rather than handling routing specifically).

Rails3: Appropriate use of routing and resources

I've recently joined the world of Rails app development (Rails3) and I may be abusing resourceful routing.
The default resourceful routing makes some really convenient helper methods for the URLs which I use constantly. My problem is that I have controllers that I specified the routing as resourceful simply to take advantage of those helper methods. I have some basic site navigation that has no business with resources.
resource :home do
member do
get 'main'
get 'about'
get 'login'
get 'help'
end
end
Is there a better way to do what I've been doing? Anything that doesn't require that I manually add routing entries each time I have a new controller action?
Just to clarify, I want to specify routing for a controller without having to explicitly add any new actions but I also want it to auto-generate helper methods. So far, I have to explicitly add routes for each action I want that for. I can get something similar by doing this (in a non-resourceful way),
match 'home/about' => 'home#about'
But I don't want to have to write that very every route that doesn't fall into the convention.
Here's another simpler one. Just add a generic route to the bottom of your routes.rb
match ":controller/:action"
and it will map directly to the specified action of the specified controller. You can be a bit more specific if you like. For example, using get instead of match to restrict to HTTP GET requests, specifying the applicaple controllers etc.
get ":controller/:action", :constraints => { :controller => /home|help/ }
You can look into your controller for public instance methods and generate routes automatically.
# routes.rb
HomeController.public_instance_methods(false).select{|m| !(m.to_s =~ /^_/)}.each do |m|
match "home/#{m}", :action => m, :controller => HomeController, :as => "home_#{m}"
end
This will take the explicit(non-inherited) public instance methods from your controller, and select the ones that don't begin with an underscore(because underscored ones are generated methods for filters, the rest are actual actions). Then it will generate a named route for each.
Keep in mind that routes.rb is processed only at server startup so you will have to restart the server after you add new actions.

Resources