Finding records in controllers

I’m going through the “Rails Controller and Views Part 2” video and filling out the CardsController. When I gave it a shot myself, I had used:

@deck = Deck.find(params[:deck_id]) @card = Card.find(params[:id])

but the video suggests using:

@card = @deck.cards.find(params[:id])

I’m curious about why you use one versus the other. Is it a matter of efficiency, because you have access to a smaller selection of cards through @deck?

The main point I am familiar with is usually to scope in ActiveRecord using joins. In this case, you would do this to ensure that the card that you are looking up belongs to the deck you are looking up. This is generally a good thing to do when you deal with nested resources.

An example that may demonstrate this better would be something like this. Given a User with an id of 1 and a SuperSecretThing with an id of 2 that does not belong to that user, I can visit the url http://localhost:3000/users/1/super_secret_things/2

Using the first method:

def show
  @user = User.find(params[:user_id])
  @super_secret_thing = SuperSecretThing.find(params[:id])
end

This will return the super secret thing regardless of whether user 1 actually owns that super secret thing.

Using the second method:

def show
  @user = User.find(params[:user_id])
  @super_secret_thing = @user.super_secret_things.find(params[:id])
end

This scopes the find on the SuperSecretThing to user 1’s super secret things by performing a join in ActiveRecord between the users and super_secret_things table. This will result in an ActiveRecord::RecordNotFound exception being thrown.

2 Likes

Thanks so much! Great explanation.