I’ve read over 20 StackOverflow pieces (and plenty others across the web) on very similar issues and tried their solutions, but none of it has worked. Please help this beginner!
In particular, the solution I’ve found most often is
form_for [@parent, @child] do |f|
but it doesn’t fix the error the way it did for other people.
Error:
The error occurs at localhost:3000/locations/1/restaurants/new
NoMethodError in Restaurants#new
Showing /app/views/restaurants/_form.html.erb where line #1 raised:
undefined method `restaurants_path' for #<#<Class:0x007fb7ab89ea80>:0x007fb7aaadc3c0>
Extracted source (around line #1):
1: <%= form_for [@location, @restaurant] do |f| %>
2: <% if @restaurant.errors.any? %>
3: <div id="error_explanation">
4: <h2><%= pluralize(@restaurant.errors.count, "error") %> prohibited this restaurant from being saved:</h2>
I can’t find any mention of restaurants_path in any of the app code, so I’m assuming it’s some magical Rails default.
Code:
I’m using has_many/belongs_to models: A location has many restaurants.
config/routes.rb
resources :locations do
resources :restaurants
end
$ rake routes
location_restaurants GET /locations/:location_id/restaurants(.:format) restaurants#index
POST /locations/:location_id/restaurants(.:format) restaurants#create
new_location_restaurant GET /locations/:location_id/restaurants/new(.:format) restaurants#new
edit_location_restaurant GET /locations/:location_id/restaurants/:id/edit(.:format) restaurants#edit
location_restaurant GET /locations/:location_id/restaurants/:id(.:format) restaurants#show
PUT /locations/:location_id/restaurants/:id(.:format) restaurants#update
DELETE /locations/:location_id/restaurants/:id(.:format) restaurants#destroy
app/controllers/restaurants_controller.rb
def new
@restaurant = Restaurant.new
respond_to do |format|
format.html
format.json { render json: @restaurant }
end
end
def edit
@restaurant = Restaurant.find(params[:id])
end
def create
@location = Location.find(params[:location_id])
@restaurant = @location.restaurants.create(params[:restaurant])
respond_to do |format|
if @restaurant.save
format.html { redirect_to location_restaurants_path(@location), notice: 'Restaurant was successfully created.' }
format.json { render json: @restaurant, status: :created, location: @restaurant }
else
format.html { render action: "new" }
format.json { render json: @restaurant.errors, status: :unprocessable_entity }
end
end
end
You have not initialized a
@location, which is required for your form (in the lineform_for [@location, @restaurant]). Just add a line that looks it up (usingLocation.find) to yournewaction and then build@restaurantso that it is associated with the location:Since you’ll need
@locationfor all your actions (includingedit, which I assume must not be working either in your current code), it would make sense to put it into a separate method and then call it from abefore_filter, i.e.:Then you can also remove the line where you find the location in your
createaction (and from thenewaction).