Rails 3 Routes and Namespaces - ruby-on-rails-3

I have recently inherited an app where a user's edit account methods along with public account methods all live in the same controller. I am looking to try to make things a little more "Rails-esque" to clean the app up.
Here are the current routes
resources :user, :only => [:update, :show] do
member do
get :edit_account
put :edit_account
put :update_billing_information
put :update_account_type
get :edit_vitals
get :edit_videos
get :edit_athletic
get :edit_academic
get :edit_social
get :edit_news
get :edit_contributors
get :edit_primary_sport_positions
get :edit_primary_sport
get :edit_primary_sport_highlights
delete :remove_alternate_position
get :vitals
get :videos
get :athletic
get :academic
get :social
get :news
post :keep
post :draft
get :share
post :share
get :notes
post :notes
get :contact
post :contact
post :cut
delete :deactivate_account
delete :delete_authorization
end
get :change_current_sport, on: :collection
end
I reckon what I am looking for is, what would be the best rails best practices to move this towards routes that resemble /user/edit/account or /user/edit/billing?

Related

Nested resources in view page. (3 levels)

I believe we are all familiar with the normal posts and comments models to be displayed. Now imagine those relations hold. I would like to add replies to my comments so we have routing as follows
resources :posts do
resources :comments do
resources :replies do
end
end
I tried many different ways of implementing this in my views but I had no luck! It just does not work when my actual controller is post and I want to access replies. I tried searching for this but did not find the suitable name for it. Is there any resource that have information about how to implement this system or a code snippet on how to make it work on n levels instead of just 2?
http://nithinbekal.com/posts/rails-shallow-nesting/
You can use shallow nesting instead.
resources :posts, shallow: true do
resources :comments do
resources :replies do
end
end
This way you only have a nested route when you need to create a nested object [new and create action] or see all the related objects [index view]. Look at the first three lines below to see what i mean. And then you have normal routes for the resources that dont need to know the relation.
comment_replies GET /comments/:comment_id/replies(.:format) replies#index
POST /comments/:comment_id/replies(.:format) replies#create
new_comment_reply GET /comments/:comment_id/replies/new(.:format) replies#new
edit_reply GET /replies/:id/edit(.:format) replies#edit
reply GET /replies/:id(.:format) replies#show
PATCH /replies/:id(.:format) replies#update
PUT /replies/:id(.:format) replies#update
DELETE /replies/:id(.:format) replies#destroy
post_comments GET /posts/:post_id/comments(.:format) comments#index
POST /posts/:post_id/comments(.:format) comments#create
new_post_comment GET /posts/:post_id/comments/new(.:format) comments#new
edit_comment GET /comments/:id/edit(.:format) comments#edit
comment GET /comments/:id(.:format) comments#show
PATCH /comments/:id(.:format) comments#update
PUT /comments/:id(.:format) comments#update
DELETE /comments/:id(.:format) comments#destroy
posts GET /posts(.:format) posts#index
POST /posts(.:format) posts#create
new_post GET /posts/new(.:format) posts#new
edit_post GET /posts/:id/edit(.:format) posts#edit
post GET /posts/:id(.:format) posts#show
PATCH /posts/:id(.:format) posts#update
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format)
Rule of thumb:
Resources should never be nested more than 1 level deep.
I suggest you to read this article by Jamis Buck. You probably want to do something like:
resources :posts do
resources :comments
end
resources :comments
resources :replies
end

how can I make a simple route on rails and can I use it for an ajax form?

Ive been trying to create a simple route on rails, following this instructions
http://guides.rubyonrails.org/routing.html
my problem is that when I want to enter to my method I get a weird error.
I have a controler user and on my routes I wrote something like this
resources :users do
match "/custom/" => "user#custom"
end
So, at my controller I add this code
def custom
#user = User.find(params[:user_id])
end
but when I try to enter doing localhost:3000/users/1/custom I get an error like
uninitialized constant UserController
doing rake routes I can see
user_custom /users/:user_id/custom(.:format) user#custom
Any idea how to solve this problem?
I want this route to submit a form... is it possible to use this route (if i make it run) for use ajax? I want to submit a form.
Thanks
Change your route to:
resources :users do
match "/custom/" => "users#custom"
end
You should avoid the use of match though, since it will be deprecated in Rails 4. Try this instead
resources :users do
get :custom, on: :member
end
get is the verb, :custom the route and on: :member means that you are looking for a /users/:id/custom route instead of a /users/custom one. If you are looking for the latter, do this:
resources :users do
get :custom, on: :collection
end
Another way to do it is like this, which I prefer:
resources :users do
get 'custom', on: :collection
end
That gives you a route of /users/custom. If you were do use on: :member, then it would give you a route of /users/:id/custom.
You can also use a block for defining multiple custom actions for collections or members.
For example:
resources :users do
collection do
get 'custom'
post 'some_other_method'
end
member do
get 'some_action'
end
end

Rails _path helper generating path with format not id

In my routes.rb I have:
resources :aquariums do
resources :management_roles
resources :graphs
resources :animals
end
get 'aquarium', to: 'aquariums#show', :as => :aquarium
The reason for the last get is I have the notion of "current aquarium" in my app. If, say, current_aquarium is set to 1, then in my controller's 'show' action '/aquarium' gets the same rendering as '/aquariums/1' with code like
#aquarium_id = params[:id] || current_aquarium.id
Now, and I'm assuming this is thanks to this different routing, this code:
<%= link_to aquarium.name, aquarium %>
or
<%= link_to aquarium.name, aquarium_path(aquarium) %>
Generates paths like this:
/aquarium.1
where I'd typically expect:
/aquariums/1
Right?
Per request... here's what rake routes | grep aquar yields:
(I'm assuming it's that very last route that is messing things up, but I would have thought that it would process these in order. And, just FYI, I originally had that route at the top. Moved it to the bottom assuming it would fix).
aquarium_management_roles GET /aquariums/:aquarium_id/management_roles(.:format) management_roles#index
POST /aquariums/:aquarium_id/management_roles(.:format) management_roles#create
new_aquarium_management_role GET /aquariums/:aquarium_id/management_roles/new(.:format) management_roles#new
edit_aquarium_management_role GET /aquariums/:aquarium_id/management_roles/:id/edit(.:format) management_roles#edit
aquarium_management_role GET /aquariums/:aquarium_id/management_roles/:id(.:format) management_roles#show
PUT /aquariums/:aquarium_id/management_roles/:id(.:format) management_roles#update
DELETE /aquariums/:aquarium_id/management_roles/:id(.:format) management_roles#destroy
aquarium_graphs GET /aquariums/:aquarium_id/graphs(.:format) graphs#index
POST /aquariums/:aquarium_id/graphs(.:format) graphs#create
new_aquarium_graph GET /aquariums/:aquarium_id/graphs/new(.:format) graphs#new
edit_aquarium_graph GET /aquariums/:aquarium_id/graphs/:id/edit(.:format) graphs#edit
aquarium_graph GET /aquariums/:aquarium_id/graphs/:id(.:format) graphs#show
PUT /aquariums/:aquarium_id/graphs/:id(.:format) graphs#update
DELETE /aquariums/:aquarium_id/graphs/:id(.:format) graphs#destroy
aquarium_animals GET /aquariums/:aquarium_id/animals(.:format) animals#index
POST /aquariums/:aquarium_id/animals(.:format) animals#create
new_aquarium_animal GET /aquariums/:aquarium_id/animals/new(.:format) animals#new
edit_aquarium_animal GET /aquariums/:aquarium_id/animals/:id/edit(.:format) animals#edit
aquarium_animal GET /aquariums/:aquarium_id/animals/:id(.:format) animals#show
PUT /aquariums/:aquarium_id/animals/:id(.:format) animals#update
DELETE /aquariums/:aquarium_id/animals/:id(.:format) animals#destroy
aquariums GET /aquariums(.:format) aquariums#index
POST /aquariums(.:format) aquariums#create
new_aquarium GET /aquariums/new(.:format) aquariums#new
edit_aquarium GET /aquariums/:id/edit(.:format) aquariums#edit
aquarium GET /aquariums/:id(.:format) aquariums#show
PUT /aquariums/:id(.:format) aquariums#update
DELETE /aquariums/:id(.:format) aquariums#destroy
aquarium GET /aquarium(.:format) aquariums#show
Thanks in advance!
Greg
Change that last route from this:
get 'aquarium', to: 'aquariums#show', :as => :aquarium
to this:
get 'aquarium', to: 'aquariums#show', :as => :current_aquarium
The problem is that you have to routes named the same thing:
aquarium GET /aquariums/:id(.:format) aquariums#show
aquarium GET /aquarium(.:format) aquariums#show
If you make the change above then that second route will not match when you make those link to calls... as it stands now, the second one is matching and like the route says is using your argument as the :format.
If you do make this change, you may need to tweak some things if you are intentionally linking to 'current_aquarium'.

Nested Routing for Single Table Inheritance model rails 3.1

I created a Single table inheritance model in my model file and am having difficulty with the routing. When I use :as in my resource, it renames my named path.
Model file:
class Account < ActiveRecord::Base
belongs_to :user
end
class AdvertiserAccount < Account
end
class PublisherAccount < Account
end
Routes.rb
resources :advertiser_accounts, :as => "accounts" do
resources :campaigns
end
I used :as in my routes because it is a single table inheritance and I want to pass the account_id and not the advertiser_account_id. My link is http://127.0.0.1:3000/advertiser_accounts/1/campaigns
/advertiser_accounts/:account_id/campaigns/:id(.:format)
However, using :as renames my named path from advertiser_account_campaigns to account_campaigns. My route looks like
account_campaigns GET /advertiser_accounts/:account_id/campaigns(.:format) campaigns#index
So when I create a new item using form_for, I would get "undefined method `advertiser_account_campaigns_path'"
Edited: current hacked solution
A hack around way that I am using is to duplicate the code in the routes file. Anyone have suggestions?
resources :advertiser_accounts, :as => "accounts" do
resources :campaigns
end
resources :advertiser_accounts do
resources :campaigns
end
If you run "rake routes" with your setup you'll see this:
account_campaigns GET /advertiser_accounts/:account_id/campaigns(.:format) campaigns#index
POST /advertiser_accounts/:account_id/campaigns(.:format) campaigns#create
new_account_campaign GET /advertiser_accounts/:account_id/campaigns/new(.:format) campaigns#new
edit_account_campaign GET /advertiser_accounts/:account_id/campaigns/:id/edit(.:format) campaigns#edit
account_campaign GET /advertiser_accounts/:account_id/campaigns/:id(.:format) campaigns#show
PUT /advertiser_accounts/:account_id/campaigns/:id(.:format) campaigns#update
DELETE /advertiser_accounts/:account_id/campaigns/:id(.:format) campaigns#destroy
accounts GET /advertiser_accounts(.:format) advertiser_accounts#index
POST /advertiser_accounts(.:format) advertiser_accounts#create
new_account GET /advertiser_accounts/new(.:format) advertiser_accounts#new
edit_account GET /advertiser_accounts/:id/edit(.:format) advertiser_accounts#edit
account GET /advertiser_accounts/:id(.:format) advertiser_accounts#show
PUT /advertiser_accounts/:id(.:format) advertiser_accounts#update
DELETE /advertiser_accounts/:id(.:format) advertiser_accounts#destroy
So you should use "account_campaingns_path" in this setup, the ":as" actually changes the calls in the code not the paths in the url. If you want to change the paths you should use ":path =>" rather than ":as =>".
The Rails guide on routing also shows some examples with ":as" and ":path" and the resulting paths and helpers, you'll need to search a bit because think they only use in in examples explaining other cases.
Edit: rereading your question, I think you may also want to look at member routes, I'm not sure if that's what you want to mean with it being a single inheritance and not wanting to pass the advertiser_account's ':account_id'?

Defining a route for a method in rails 3

I'm new to Rails and currently using Rails 3, so please bear with me. I have a basic app, with a basic scaffolded controller/model e.g Contacts.
Amongst the methods for Show/Edit etc.. i have added a method called newcontacts (i have also added a newcontacts.html.erb), which will eventually show the last 5 contacts imported , but at the moment i am using the same code one would find in the basic Index method of a controller (i intend to filter the data at a later point), the method in the controller is -
def newcontacts
#contacts = Contact.all
respond_to do |format|
format.html # index.html.erb
end
end
I can access localhost:3000/contacts which displays the index method action from the contact controller, but when i try and access this method (newcontacts) using localhost:3000/contacts/newcontacts it returns the error
Couldn't find Contact with id=newcontacts
I have looked at the routes.rb file as i believe this is what needs editing, and have added the following line to routes.rb
match 'newcontacts', :to => 'contacts#newcontacts'
but this only works when i call localhost:3000/newcontacts.
So my question is, how do i get the url localhost:3000/contacts/newcontacts to work?
Any help would be great.
I think what you're trying to do is add another RESTful action.
resources :contacts do
# This will map to /contacts/newcontacts
get 'newcontacts', :on => :collection # Or (not and; use only one of these)...
# This will map to /contacts/:id/newcontacts
get 'newcontacts', :on => :member # ... if you want to pass in a contact id.
end
Try this in your routes.rb file:
resources :contacts do
member do
put 'newcontacts'
end
end
That will add in a new action for the contacts controller.