I have a client controller and views which already functions for all the default actions. How do I add a new_account and create_account actions that also work with routing?
The idea is... there are new clients, but some clients can also function as an account that logs into the website. I want to prompt for different fields based on whether a client is being created or a login account is being created. I don't want two separate models with duplicate information.
client_controller.rb - index, new, create, edit, update, destroy, new_account, create_account
client views - I have views for each of the actions within the controller.
Routing - ../new_account should display the new_account view for the client model, not the new view.
Hopefully this makes sense. I'm guessing this isn't difficult but I'm just missing how.
Try:
match 'new_account', 'client#new_account', :via => :get
match 'create_account', 'client#create_account', :via => :post
View all your routes by running rake routes.
Refer to more info on routing here: http://guides.rubyonrails.org/routing.html
Put this in your routes.rb
resources :clients do
new do
scope type: 'account' do
get :account, to: 'clients#new'
post :account, to: 'clients#create'
end
end
end
and the actions you need will be accessible at GET|POST /clients/new/account.
In the controller you'll have params[:type] to indicate this specific case.
Related
The guide Rails Routing from the Outside In has a section named Adding Routes for Additional New Actions in chapter 2, Resource Routing: the Rails Default, with this example:
resources :comments do
get 'preview', on: :new
end
which generates the following route:
Prefix Verb URI Pattern Controller#Action
preview_new_comment GET /comments/new/preview(.:format) comments#preview
The same result can be achieved at least in two other ways:
1) Adding a collection route inside resources :comments like get 'new/preview', to: :preview, on: :collection (if you don't bother about the route name)
2) Adding just this route to the corresponding singular resource:
resource :comment, only: :preview do
get 'new/preview', to: :preview, as: 'preview_new', on: :collection
end
which has exactly the same behavior.
So why there is a on: :new option? Is it just a shortcut? If it is, why it's just for 'new actions' and there are not any similar options for the other default REST actions, like on: :edit or on: :delete?
This is a shortcut that is unique to the RESTful action new, in which an object is instantiated but not yet persisted.
For example, if you are filling out a form for a new object, you would provide yourself with a link_to "preview", which sends all of the attributes to your preview action (instead of directly to create). This is similar to a show view, but for an object that only exists in memory.
This functionality isn't logical for destroy, update, index, show or create. I suppose you could use a preview on an edit action after assigning new attributes before sending to update, but you'd have to create the route manually.
Actually there is a subtle difference.
If you add it to the resources :comments the path helper generated has a pluralized resource name so it will be preview_new_comments and the path will be /comments/new/preview. If you add it to the corresponding singular resource it doesn't pluralize the resource name in the path so you get /comment/new/preview but the helper will be preview_new_comment. Using :on will generate the path helper with the singular resource preview_new_comment but the route will have the pluralized resource /comments/new/preview.
To get the same behaviour you could use the following more verbose route outside the resource
get 'collections/new/preview', to: 'collections#preview', as: :preview_new_comment, on: :collection
I'm not sure why there is no on: :<action other than new> option. They advise against having too many new actions in the documentation but if you are going to have a new 'new' it seems a reasonable possibility you might need an new 'edit' to edit your new 'new'. However, things become more complicated because to edit you would need a path like collections/<id>/edit/preview and the path helper of the solution above stops working as you might expect. More importantly at this stage maybe you start veering away from the original intention of the option.
I have a resource - activities, that is nested under provider. everything is working great for all my restful resources.
I'd like to add a new action to list all activities regardless of provider. So I think that should not be nested.
I tried to do this like so:
resources :activities, only: [:list]
But this doesn't create a route when i rake routes, and I get the error:
No route matches [GET] "/activities/list"
How do I do this? Is this the right way to go about what I want to do - show a list of all providers activities with a different view / layout than the nested provider#activities action.
OK. I (re) read the manual and did what it said, and that worked. Go figure.
resources :activities do
get 'list', :on => :collection
end
So that adds the list action to the routes with path & url methods & the nested resources still work.
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.
I've model called BlogPost and controller called BlogPostsController that has all basic CRUD methods for BlogPost.
I'm trying to understand how I can route users to have URL like /blog/post-name instead of /blog_posts/post-name and "disable" in general URL /blog_posts. Should I rename my controller or should I change routes (and how)?
Update your routes and add the :as option to your blog post resource route
map.resources :blog_posts, :as => 'blogs'
I seriously cant understand why this is so hard... I have some experience with other mvc frameworks but always heard rails was the easiest to code in.... right now I cant even get to my controller methods if i want to.
I used scaffold to creat 'student' which automatically created for me the controller, model and views for basic CRUD.. but now I just want to add a method "helloworld" to my controller and when i go to
http://localhost:3000/students/helloworld
I get a
Couldn't find Student with ID=helloworld
error.
what am I missing?.. I know its got to do with routes and the REST thing but I still cant figure out then how else am I supposed to use my own methods... do I have to edit my routes.rb file everytime I create a new method?.. please help
Routes for models in Rails are divided into 2 groups. Ones that act on a single objects (think edit, update, delete) and ones that don't have a single object to act on (new, index). If you want to create your own method that doesn't take an object ID you need to add a route config for that method in your routes file. The methods are either member or collection methods. Member methods URLs look like /model/id/method_name. Collection methods look like what you want (/model/method_name). Here is an example for your students model (routes.rb)
map.resources :students, :member => {:some_member_function_example => :get },
:collection => { :helloworld => :get }
Note: You can just remove the :member => ... from the config and only have collection if you have no member methods to define.
Link /students/foo will not call the foo method of the students_controller. That's because REST mappings in Rails includes /:controller/:id route for GET. And your link matches this pattern.
In order to override that path (for methods with no parameters, like yours) use the following snippet:
map.resources :students, :collection => {:method_name => :get}