Rails 3, help controlling access to a record based on the user id

Hello, I'm a Rails newbie.... Here's what I'm trying to do....

I created a scaffold for notes (t.text :content, t.integer :user_id)
What I want to do now is only allow user's to view notes that they
created. ie (== user_id)

In my /app/controllers/notes_controller.rb

I have the following:

    class NotesController < ApplicationController
      before_filter :authenticate
      before_filter :correct_user
    def correct_user
      @noteuserid = Note.find(:conditions=>["note.user_id=?",
      redirect_to(root_path) unless current_user?(@noteuserid)

I'm having problems understanding how to write the following line:
@noteuserid = Note.find(:conditions=>["note.user_id=?", @noteuserid])

Right now I'm using the system in the Rails 3 Tutorial Book:

Seems like the problem is current_user is an object, not an ID... Not
sure how to make the two comparable?


This hack ends up working. Is there a cleaner, ruby trick to getting
this to work?

      @note = Note.find(params[:id])
      @note_userid = @note.user_id
      @current_userid = current_user.id
      redirect_to(root_path) unless @current_userid == @note_userid


The cleanest method is to scope your notes by user instead of
searching the whole class:

@note = @user.notes.find(params[:id])

Ed thanks for the reply. I'd love to hear more... I tried your
suggestion but it error'd:

"undefined method `Notes' for nil:NilClass"

Two possible issues:

1. Do you have the relationship declared in the models?

class Note < ActiveRecord
  belongs_to :user

class User < ActiveRecord
  has_many :notes

2. If @user is a nil object, it will throw an error. Set @user to
the current_user in your before_filter. If there is a possibility of
hitting that point with a nil user, then change the line to read
something like this:

@note = @user ? @user.notes.find(params[:id]) : nil

which is a shorter way of saying

if @user.nil?
  @note = nil
  @note = @user.notes.find(params[:id])

Thanks for the reply, I do have the relationships declared above in
the models... I've been learning and following the rails 3 book here:

I tried your suggestion "@note = @user ?
@user.notes.find(params[:id]) : nil " and while it didn't error which
was good, it didn't work, it ended up redirecting... Full code:

class NotesController < ApplicationController
  before_filter :correct_user, :only => :show
  def show
    @note = Note.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.xml { render :xml => @note }

    def correct_user
      #@note = Note.find(params[:id])
      #@note_userid = @note.user_id
      @note = @user ? @user.notes.find(params[:id]) : nil
      @current_userid = current_user.id
      redirect_to(root_path) unless @current_userid == @note_userid

please check the post "Use scope access" on rails-bestpractices.com,
http://rails-bestpractices.com/posts/3-use-scope-access, it tells you
how to use the Ed's way to strict access and rescue the exceptions.

You don't seem to be setting @note_userid anywhere. The check is
redundant though - doing @user.notes.find(...) ensures that the
returned note (or notes) have a user_id that is @user.id. You
obviously need to set @user to somethign first (or if current_user is
set appropriately by your authentication stuff then you could do


Thanks all, this ended up working which I believe scopes correctly...

@note = current_user.notes.find(params[:id])