Question

I've got an app where the user can nominate a keyholder who can also view their account. I've got a before_filter than means that only the account holder, or their keyholder, can view their account. This code works fine for either person viewing the user's home page, but I can't do anything further - I am currently logged in as the keyholder, and I can't log out, or add 'notes' to either account (right now the keyholder has unrestricted access to their own account and the person they are keyholder for). Please can anyone help?

The before_filter is:

def correct_user
        @user = User.find(params[:id])

        unless (@user && current_user.id == @user.id) || ((current_user.access_id==@user.id)&&(current_user.id==@user.access_id))
          redirect_to root_path
        end
      end

and the error I am getting when trying to e.g. create a note is:

ActiveRecord::RecordNotFound in NotesController#new 
Couldn't find User without an ID

it is referring to the @user line in the before_filter.

How come when I am logged in as the keyholder, I can view the homepage, but do nothing else? Thanks!

UPDATE:

Updated before_filter (in application_controller.rb):

def correct_user
        if params[:id]
          @user = User.find(params[:id])

          unless (@user && current_user.id == @user.id) || ((current_user.access_id==@user.id)&&(current_user.id==@user.access_id))
            redirect_to root_path
          end
        else
          redirect_to root_path
        end
      end

Console output on note creation:

Started POST "/notes" for 127.0.0.1 at 2013-02-28 14:10:49 +0000
Processing by NotesController#create as HTML
  Parameters: {"utf8"=>"V", "authenticity_token"=>"qMDHQAoC4l3Be5YZKSH1AJ9E5zS1D
kMNCW2KzUZ38gM=", "note"=>{"user_id"=>"16", "content"=>""}, "commit"=>"Update Note"}
Redirected to http://localhost:3000/
Filter chain halted as :correct_user rendered or redirected
Completed 302 Found in 98ms (ActiveRecord: 0.0ms)


Started GET "/" for 127.0.0.1 at 2013-02-28 14:10:49 +0000
Processing by PublicController#index as HTML
  ←[1m←[36mUser Load (3.0ms)←[0m  ←[1mSELECT "users".* FROM "users" WHERE "users
"."id" = 16 LIMIT 1←[0m
  Rendered public/index.html.erb within layouts/application (5.0ms)
  ←[1m←[36mTimeline Load (3.0ms)←[0m  ←[1mSELECT "timelines".* FROM "timelines"
WHERE "timelines"."user_id" = 16 LIMIT 1←[0m
  ←[1m←[36mMessageBoard Load (2.0ms)←[0m  ←[1mSELECT "message_boards".* FROM "me
ssage_boards" WHERE "message_boards"."user_id" = 16 LIMIT 1←[0m
  Rendered partials/_menuoptions.html.erb (53.0ms)
Completed 200 OK in 551ms (Views: 535.0ms | ActiveRecord: 16.0ms)
Was it helpful?

Solution

Try:

def correct_user
            if current_user
              @user = User.find(current_user.id)

              unless (@user && current_user.id == @user.id) || ((current_user.access_id==@user.id)&&(current_user.id==@user.access_id))
                redirect_to root_path
              end
            else
              redirect_to root_path
            end
          end

Actually, there is no params[:id] like thing here. The current_user is the user whom you are checking so you can directly find with current_user.id as above. Replace the code with above and rectify for possible best if you find other. It is just an idea for implementation.

OTHER TIPS

When you go yo notes/new, you are not providing any id param, and that is the reason for you to get this exception.

You have to check first if params[:id] exists:

def correct_user
  if params[:id]
    @user = User.find(params[:id])

    unless (@user && current_user.id == @user.id) || ((current_user.access_id==@user.id)&&(current_user.id==@user.access_id))
      redirect_to root_path
    end
  else
    redirect_to root_path
  end
end

and in the link to notes/new you have to provide the id param for the user:

<%= link_to "New note on #{@user.name}", new_note_path(id: @user.id) %>

I think that you're validating too much on a single action, anyway the problem seems to be in the get/post request, since there is no id getting to the controller action, can you attach the params being sent to the controller? copy them from the console, it will be easier to read...

 "note"=>{"user_id"=>"16", "content"=>""}

You've to use params[:note][:user_id] to get the user id, you'll have to add a hidden field with the user id for being able to do what you want, if you ask me, I don't see it as a good practice, have you seen any railscast?, I'm pretty sure that you can find a lot of helpful tips on there, look at this one for example:

Railscast Cancan

Hope it helps...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top