Been working in another language for a few months and trying to get back into Rails.
If I have a model House, and a model Door, so that Door belongs_to House and House has_many Doors.
If I want to add a door to the house, do I use the route:
add_door_path
or is it
add_door_path(#house)
And if so how do I embed the house_id in to it? Or do I need to create a new route for that? Is it part of the standard resources or is this entirely custom?
if you have
# routes.rb
resources :house do
resources :doors
end
then you would have house_doors_path(#house)
That is because in your routes you have specified that doors is nested inside the house. You would need the parameter inside because the path requires a house id.
To check for the routes, go here http://localhost:3000/rails/info/routes.
If on the other hand, if you have
# routes.rb
post '/door/' => 'doors#create', as: :add_door
the new door would not know which house it belongs to. so you can add
post '/house/:id/door ... which you also need a parameter of house so your syntax would be add_door_path(#house)
I hope that answers your question.
Related
I have two models:
class GarageOwner < ActiveRecord::Base
has_many :garages, dependent: :destroy
end
class Garage < ActiveRecord::Base
belongs_to :garage_owner
end
A Garage should never exist without a garage owner. So in the new action of the GaragesController I need the corresponding garage owner. I do not want to use nested routes so I do not have the garage owners id as a parameter. But how do I get him then?
Update for some clarification
Garages are created by a third model (Admin). So I can not access the garage owner through the current user.
I build my routes using resources:
garage_owners GET /garage_owners(.:format) garage_owners#index
POST /garage_owners(.:format) garage_owners#create
new_garage_owner GET /garage_owners/new(.:format) garage_owners#new
edit_garage_owner GET /garage_owners/:id/edit(.:format) garage_owners#edit
garage_owner GET /garage_owners/:id(.:format) garage_owners#show
PUT /garage_owners/:id(.:format) garage_owners#update
DELETE /garage_owners/:id(.:format) garage_owners#destroy
garages GET /garages(.:format) garages#index
POST /garages(.:format) garages#create
new_garage GET /garages/new(.:format) garages#new
edit_garage GET /garages/:id/edit(.:format) garages#edit
garage GET /garages/:id(.:format) garages#show
PUT /garages/:id(.:format) garages#update
DELETE /garages/:id(.:format) garages#destroy
The solution to not using nested routes is to insert the garage_owner_id as a hidden field in your new garage form. But, you've given no indication in your question of how the new garage form is meant to know about which garage_owner it should associate with so I can't give you a specific example.
Perhaps I'm not getting your question, but I think you'd have to either pick up the garage owner from your session (e.g. logged in user), or something derived from a value in your session or as a value submitted with the form used for the new operation, in which case it would be a parameter.
You could approach this a couple different ways:
If the GarageOwer requires a login, you could grab the ID of the GarageOwer user from the cookie stored at login.
Create a custom route match "/Garages/new/:owner_id" => "garages#new", there after in your controller access the owner's id via params[:owner_id].
Add owner_id as a hidden attributed to the form on the "garages/new" page.
I found an appropriate solution which is still restful I think. I just created multiple routes for garages:
resources :garage_owners do
resources :garages, except: :index
end
resources :garages, only: [:index, :show]
Normal users should not access the other actions.
I'm trying to understand the best way to architect a fairly simple relationship. I have a Job Model and a Category Model with a has_many relationship between them in a JobCategories model.
I'd like to have a page that lists all Jobs for a specific Category. Should the logic to pull this data be on the Category Controller (on the show action), or should I create a category method on the Job Controller? My gut tells me it should be on the Category side because a Category has Jobs, but it doesn't feel right that a Job would have the logic to pull all the Jobs for a given category.
Having said that, if I want the URL to be something that is more Job specific like:
domain/jobs/:id/{category-name} (for SEO purposes)
How would I structure the route so that it reads like the above, as opposed to
domain/categories/:id
which is what you'd get with resources :categories, only: [:show]
Thanks!
For a pretty slug, I'd suggest using FriendlyId on your categories model.
As for the routes, you will not get the desired route using resources :categories
One way to do it would be
resources :jobs, only: [] do
member do
get '/:slug' => 'categories#some_action'
end
end
the slug will be passed in your parameters.
This will yield a route like this
GET /jobs/:id/:slug(.:format) categories#some_action
UPDATE
the :slug is just an example for pretty url.
In your case you'd want to have :category_name. That would be passed into your controller through the params[:category_name].
One thing that I did start thinking when I re-read your question is that you want to show a list of jobs for a specific category. A url path like /jobs/:id/{category-name} shouldn't actually show a list of jobs as you are specifying an id which means a specific job. I think the url that you're looking to get is more along the lines of /jobs/{category-name}. Am I correct?
UPDATE 2
I suggest you read this Ruby On Rails Routing
UPDATE 3
Since you did want an url more like /jobs/{category-name}
You're routes should look like this
resources :jobs, only: [] do
collection do
get '/:category_name' => 'categories#some_action'
end
end
Good luck with your project! :D
I have a many-to-many relationship between users and teams (as a has_many :through), and I'm trying to setup a "team members" join model as a resource in the routes.
In my layouts I've setup a "team context form" that sets a session variable for the current_team, and I want the route for the team_members resources to be defined as /team_members/:user_id/show. Is there any way to do this with the resources :team_members in routes.rb?
I've tried using :path_names => {:action => "\some\url"}, however for actions that require an :id the router appends the route to be something like "\:id\some\url"
edit:
If you want to be able to edit the team membership, you could have
resources :users do
resources :team_members
end
and then, to edit the membership => /users/:user_id/team_members/:id/edit
And then you can do whatever you want in the team_members_controller.
Or as numbers1311407 said, just resources :team_members and you'll have all the rest routes to work with the team memberships.
Really don't want the standard /teams/:team_id/users/:id ?
If you really want /team_members/:user_id/show
You could just do
get "/team_members/:id/show" => "users#show"
But I dont think it's a good idea.
I wonder if what you're looking for is:
resource :team_members do
resources :users
end
The "resource" command creates a route where team takes no :id and would allow you to look up the team using your current_team session variable.
You'd get these path in your app:
/team_members # team_members#show
/team_members/users # users#index
/team_members/users/:id # users#show
In each case you're responsible for looking up current_team.
if the relationship is many-to-many then the route you're looking to write doesn't reference the team, unless this show page is intended to show all teams a user belongs to?
This would work out of the box if you assigned an ID to the join model and simply used its natural GET route, e.g. /team_memberships/:id
Edit: sorry I didn't read the 2nd paragraph carefully, if you are storing the team in the session you could (as suggested by someone else) set up team_members as a singleton resource and pull the team from the session when getting the member.
If it works in the app, though, considering team_membership as its own resource is probably more naturally RESTful.
Trying to set up very basic association between Customer and Contact model.
Customer has_many :contacts
Contact belongs_to :customer
User has_many :customers
Routes
resources :customers do
resources :contacts
end
I don't want /contacts to be accessible
When I add in my views
new_customer_contacts_path
I have an error. If I have
new_customer_contact_path(contact)
it works however link to contact#show is wrong
--> it directs to customers/7/contact/2 where it should be customers/2/contact/7
Any idea?
new_customer_contact_path(contact)
This is wrong. You should pass customer to it instead of contact.
If you want to show the contact of a customer, you should use customer_contact_path(customer, contact).
For reference, go to http://guides.rubyonrails.org/routing.html and search 'Creating Paths and URLs From Objects'
You gotta tell the customer whose contact belongs_to!
Like the following:
# Customer.first and Contact.first can be exchanged to instances
# of Customer or Contact!
new_customer_contacts_path(Customer.first)
edit_customer_contact_path(Customer.first, Contact.first)
customer_contacts_path(Customer.first)
With nested routes you need to pass the objects (or at least their ids) in the order they are listed in the route. In the case of 'new' you only need to pass the parent object id as there is no id yet for the new nested object.
new_customer_contact_path(customer)
I'm working on a rails app and using a singular resource. However the controller name for the singular resource is plural.
Eg map.resource activity_report expectes the activity_reports_controller.
The explanation given in the rails 3 guide is: "... you might want to use the same controller for a singular route and a plural route..." That is a reasonable explanation, but what is the use case for using the same controller to handle a singular route and a plural route?
In a RESTful Rails application there is usually a mapping of one controller per RESTful resource. For example, let's say we wanted a controller to process user logins (/session) but also to provide a list of users who are currently logged in (/sessions). Logically we could put both of those responsibilities within a SessionsController:
class SessionsController < ApplicationController
# GET /sessions
# Display a list of logged in users
def index
...
end
# GET /session/new
# Display the login form
def new
...
end
# POST /session
# Authenticate a user
def create
...
end
end
An alternative would be to split the functionality for listing logged in users out into a separate administration controller.
You can use it.
class UsersController < Application
end
map.resource :user
map.resources :users
Another situation in which I can imagine using it would be, let's say (and this isn't necessarily the business model you'd want, but stay with me for a moment) you are going to make a site of film reviews, and film information. So, on the one hand you'd have the link to your list of the latest reviews be a plural resource route, something like this:
http://yoursite.com/reviews?count=5
So, in this case, you have a controller for the collection, right? But you're only going to review each movie once. So what if you wanted to provide an easy access to a movie's review?
http://yoursite.com/movies/pirates_of_the_carribean_2/review
Well, there's a nested single resource route, because a movie has_one review, right?