Paul
Paul

Reputation: 51

Using Devise, how do I make it so that a user can only edit/view items belonging to them

I've been struggling with this for a while now, so I thought I'd ask the experts.

I am trying to make it so that Users can only edit/view Items that they have created using Devise.

I have Users set up and working well. Items are being created with a user associated with them and I can verify this via rails console.

def create
 @item = Item.new(params[:item])
 @item.user = current_user
end

What I am trying to do now is to make it so that once logged in, users can only see the items that they have created, and no others.

In my Items controller have tried replacing:

def index
 @items = Items.all
end

with

def index
 @items = current_user.Items.find(params[:id])
end

but this doens't seem to work for me and I get

undefined method `Items' for #<User:0x007fdf3ea847e0>

Can anyone offer any advice as to what to try next?

Thanks so much.

Upvotes: 0

Views: 1589

Answers (3)

someoneinomaha
someoneinomaha

Reputation: 1304

If I'm understanding your question, I think you might want to check out an authorization library - like CanCan to do this.

https://github.com/ryanb/cancan

It works pretty slick to handle permission type things like this. Many people use this library in conjunction with Devise.

Upvotes: 1

Victor Pudeyev
Victor Pudeyev

Reputation: 4539

  1. Maybe I`m old school but I would not use current_user to find records, only to verify permissions. I would use the primary key relationships directly (they don't change):

    @items = Item.find(:all, :conditions => { :user_id => current_user[:id] }

or

@items = Item.find_all_by_user_id current_user[:id]

As for setting permissions, devise actually doesn`t let you do that BUT there is the excellent supplement called Cancan, you should definitely look into it. With Cancan, you will have an ability.rb class that will define your permissions. What you are looking for then becomes:

class Ability
  can [:read, :show, :edit, :update, :delete, :destroy], Item do |item|
    item.user_id == user.id
  end

  # or
  can :manage, Item do |item|
    item.user_id == user.id
  end
end

reading the Cancan docs would clarify the code above.

Upvotes: 2

Ben Schwarz
Ben Schwarz

Reputation: 57

What you're trying to do is really close…

current_user is an "instance" of the User class.

What you want to do is use the association from the user instance, which is a special method applied to every user—"items". (If the Item class also has a belongs_to :user it'll have a method called user as well)

You want current_user.items.find(params[:id])

Also, when you create it, you could also use current_user.items.create(params[:item])

Upvotes: 1

Related Questions