Reputation: 703
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.
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.
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
Upvotes: 2
Views: 250
Reputation: 27374
You have not initialized a @location
, which is required for your form (in the line form_for [@location, @restaurant]
). Just add a line that looks it up (using Location.find
) to your new
action and then build @restaurant
so that it is associated with the location:
def new
@location = Location.find(params[:location_id])
@restaurant = @location.restaurants.build
...
end
Since you'll need @location
for all your actions (including edit
, 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 a before_filter
, i.e.:
before_filter :find_location
private
def find_location
@location = Location.find(params[:location_id])
end
Then you can also remove the line where you find the location in your create
action (and from the new
action).
Upvotes: 1
Reputation: 199
I believe the issue is the way you are instantiating the @restaurant
variable in the new
action. Because it is nested under locations, you need to build it as such:
@location = Location.find(params[:location_id])
@restaurant = @location.restaurants.new
Upvotes: 0