So to simplify what I have, there are 3 main models in my application; city, restaurant and recipe. A city has many restaurants and a restaurant has many recipes. Every city has a page that lists the restaurants in that city and similarly every restaurant page has recipes listed in their page. There is also a "Add new restaurant" button in my city page, when the user clicks on this the user is taken to the new restaurant page with the following link:
<%= link_to 'Add New Restaurant', new_restaurant_path %>
But this page is a generic page that the user can add a restaurant to any city, how do i modify my design so that, that new restaurant form would only add a new restaurant to that city.
Edit: Thanks for the answers. So this is my restaurant create method right now.. Because new_restaurant_path is a form and it has other params than just a city. So i understand that I can figure out the city of my restaurant by doing @city = City.find(params[:city]) but how do I add this to the rest of the params in this line @restaurant = Restaurant.new(params[:restaurant])
def create
@restaurant = Restaurant.new(params[:restaurant])
end
With routes
You can create a route like this:
/cities/:city_id/restaurants/new
with:
resources :city do
resources :restaurants
end
and the helper:
<%= link_to 'Add New Restaurant', new_city_restaurant_path(city) %>
With params in helper
Or you can pass a parameter in your current route helper and handle it in your controller:
<%= link_to 'Add New Restaurant', new_restaurant_path(city_id: city.id) %>
This will make a use this URL:
/restaurants/new?city_id=123
For both approaches, the controller
and in the controller:
def create
city = City.find(params[:city_id])
@restaurant = city.restaurants.build params[:restaurant]
if @restaurant.save
...
end
2 ways to accomplish this
1) Add a nested route to your cities path for restaurants then use the new_city_restaurants_path(@city.id)
You would have to either create folders and views inside your cities folder or move all your restaurants folder inside the cities folder. There would also be a few other bits and piees that would need tidying up such as controllers and helpers and this may not suit.
So possibly simpler
2) add the city id to the link_to as a parameter and change the new action in the restaurants controller to check for the presence of the city id and take appropriate action so you might end up with something like this
<%= link_to 'Add New Restaurant', new_restaurant_path(:city => @city.id) %>
Then in your controller's new action add the check
def new
if params[:city]
#find the city and build a new restaurant object
city = City.find(params[:city_id])
@restaurant = city.restaurants.build params[:restaurant]
else
# just create a new restaurant object as normal
@restaurant = Restaurant.new
end
# ...Rest of action
end
edit in response to comments
Because you have built the restaurant against the city object the city id will be assigned to the restaurant object the way to deal with this depends on the code in the new.html.erb template.
If you have a city selection box then use the city id from the @restaurant object to pre select the city. That way there is no need to change any code in the params hash or the controller create action. It's difficult to advise further as I don't have your new.html.erb code
Your accepted answer deals with this in the wrong way IMO.
You might also benefit from one of Ryan Bates' nice videos on nested resources http://railscasts.com/episodes/139-nested-resources