0
votes

This is my first rails project and I'm a complete newbie to all code, not just Ruby, so please forgive me if I don't explain my issue concisely.

I have a model, Car, which belongs to another model, User. I want my Cars index page to show all cars in the database, so I made a custom route of '/cars/', rather than the :user_id/cars/:id route generated by Rails.

The Car info is getting output onto my index page, but I can't work out how to generate links back to the Car show page.

I'm sure it's something simple, but I've been reading the Rails Guide and other questions on here all day and haven't fixed it yet.

Here's the block:

                <% @cars.each do |car| %>                   
                <li>
                    <div class="well row <%= cycle('', 'white-bg')  %>">
                        <div class="col-sm-4 text-center">
                            <!-- thumbnail for car here -->
                        </div>
                        <div class="pull-left">
                            <%= link_to car.id, user_car_path(@user, car) do %>
                                <h3><%= car.year %> <%=car.make %> <%= car.model %></h3>
                            <% end %>
                        </div>
                        <div>
                            <h3 class="pull-right"><%= car.price %></h3>
                        </div>
                    </div>
                </li>                   
            <% end %>

Routes:

get 'cars' => 'cars#index', as: :cars

resources :users do
    resource :profile
    resources :cars, except: :index
end

end

Controller:

def new
    @user = User.find( params[:user_id] )
    @car = @user.cars.build
end

# POST request to /users/:user_id/cars
def create
    @user = User.find( params[:user_id] )
    @car = @user.cars.build( car_params )
    if @car.save
        redirect_to user_path( params[:user_id] )
    end
end

# GET request to /users/:user_id/cars/:id
def show
    @user = User.find( params[:user_id] )
    @car = @user.cars.find( params[:id] )
end

# GET request to /cars/
def index
    @cars = Car.all
end

The error is: No route matches {:action=>"show", :controller=>"cars", :id=>"1", :user_id=>nil} missing required keys: [:user_id]

I'm guessing I'm missing something in the controller, but everything I've tried in there just generates other errors.

Thanks!

cars_path GET /cars(.:format) cars#index

POST /cars(.:format) cars#create

new_car_path GET /cars/new(.:format) cars#new

edit_car_path GET /cars/:id/edit(.:format) cars#edit

car_path GET /cars/:id(.:format) cars#show

PATCH /cars/:id(.:format) cars#update

PUT /cars/:id(.:format) cars#update

DELETE /cars/:id(.:format) cars#destroy

new_user_profile_path GET /users/:user_id/profile/new(.:format) profiles#new

edit_user_profile_path GET /users/:user_id/profile/edit(.:format)
profiles#edit

user_profile_path GET /users/:user_id/profile(.:format)
profiles#show

PATCH /users/:user_id/profile(.:format) profiles#update

PUT /users/:user_id/profile(.:format) profiles#update

DELETE /users/:user_id/profile(.:format) profiles#destroy

POST /users/:user_id/profile(.:format) profiles#create

user_cars_path GET /users/:user_id/cars(.:format) cars#index

POST /users/:user_id/cars(.:format) cars#create

new_user_car_path GET /users/:user_id/cars/new(.:format) cars#new

GET /cars/:id/edit(.:format) cars#edit

GET /cars/:id(.:format) cars#show

PATCH /cars/:id(.:format) cars#update

PUT /cars/:id(.:format) cars#update

DELETE /cars/:id(.:format) cars#destroy

1
Could you please post the result of running rake routes? - Bustikiller
Sorry, I missed your response earlier. I've added the current routes to the OP, though they're different from when I posted the question since I have followed Max's advice below. Still not quite up and running, so if you can help I'd appreciate it! - Sam D

1 Answers

0
votes

I would suggest an alternative solution where you "unnest" the cars resource - and just provide a index route for the cars belonging to a certain user:

# routes.rb
resources :cars
resources :users do
  resources :cars, module: 'users', only: [:index]
end

# app/controller/cars_controller.rb
class CarsController < ApplicationController
  # GET /cars
  def index
    @cars = Car.all
  end

  # show, create, delete, new...
end

# app/controller/users/cars_controller.rb
class Users::CarsController < ApplicationController
  # GET /users/:user_id/cars
  def index
    @user = User.includes(:cars).find(params[:user_id])
    @cars = @user.cars
  end
end

Depending on the context you can move more of the collection routes (new, create) to Users::CarsController if you for example are able to create cars for other users. Nesting member routes (that act on a single record) is seldom necessary. You can avoid it by using the shallow: true option:

resources :users do
  resources :cars, shallow: true  
end

This lets you route to a car by simply doing:

link_to(@car.name, car_path(@car))
# or
link_to(@car.name, @car)

If you decide to keep your current setup you route to nested resource by using an array or keywords:

link_to(@car.name, user_car_path(user: @user, id: @car))
# or
link_to(@car.name, [@user, @car])