cdotfeli
cdotfeli

Reputation: 309

Creating users that belong to another user in Devise?

I'm trying to create a simple blogging application with 2 user levels: "writer" and "manager"

Writers belongs to managers, and managers can have many writers.

Writers can only see their own posts, but managers can see all the posts that their writers make.

Now my question is, how should I implement this type of system?

I'm pretty sure I should be using Devise to generate user authentication. But should I be generating separate models for each type of user (writer or model) or should I generate a roles table instead?

I don't know if that's specific enough; I spent the day racking my head over this with no solution in sight, so if you need to know more please let me know and I'll answer in the comments. Thanks in advance

Upvotes: 3

Views: 1872

Answers (4)

tquill
tquill

Reputation: 389

I like the answer from hakunin, but I think he's missing something from the user model. I think there needs to be a "source" called out, otherwise there will be a "stack level too deep" error.

# Associates posts of all writers under this manager
has_many :writers_posts, :through => :writers, :class_name => 'Post', :source => :posts

Upvotes: 0

Max Chernyak
Max Chernyak

Reputation: 37357

Sounds like a simple user table with manager_id.

create_table :users do |t|
  # ...other columns...

  t.integer :manager_id
end

class User < ActiveRecord::Base
  # Returns all writers under this manager
  has_many :writers, :class_name => 'User', :foreign_key => :manager_id

  # Returns this writer's manager
  belongs_to :manager, :class_name => 'User'

  # Allows this user to be author of posts
  has_many :posts

  # Associates posts of all writers under this manager
  has_many :writers_posts, :through => :writers, :class_name => 'Post'

  # If user has no manager, she's a manager
  def manager?
    manager_id.nil?
  end

  # If user has a manager, she's a writer
  def writer?
    !manager?
  end
end

This allows you to do the following things with your user.

if @user.manager?
  @user.writers # => [<User>, <User>, ...]
  @user.writers_posts # => [<Post>, <Post>, ...]
end

if @user.writer?
  @user.manager # => <User>
end

This implementation determines whether a user is a manager or a writer simply by the presence of a manager. If a user has a manager, she must be a writer. Else, she's a manager. If this is not flexible enough you can add extra boolean columns specifying whether user is one, the other, or even both. Also note that this is simply a User model that has both writer and manager methods. So you could call @writer.writers_posts (which is not meant to be for a writer user), but you shouldn't.

Authentication

Since all you have is a regular User model, you can follow any Devise tutorial to setup authentication for it. Both writers and managers are just users who simply login.

Authorization

As far as permissions and post visibility, it all comes down to being able to call the above methods on your current user.

if current_user.manager?
  current_user.writers_posts.each do |post|
    # display post
  end
end

So frankly, CanCan is an overkill. All you need to do is add a few before_filter and a few if current_user.manager? conditions in your views. CanCan is more comprehensive, and on my experience it's too much in most apps.

Upvotes: 7

Steve
Steve

Reputation: 4566

Yes you should use devise and you should implement an admin role for the managers that has access to all the posts. https://github.com/plataformatec/devise/wiki/How-To:-Add-an-Admin-role provides instructions on how to do this.

Upvotes: 0

cristian
cristian

Reputation: 8744

Have a look at the following gem:

CanCan for authorization More info http://railscasts.com/episodes/192-authorization-with-cancan

For you user model you could have a column specifying the user role => manager or writer, and for each user you could have a manager_id column (when a user is manager you will put null here)

Edit: You should use Devise too, for authentication

Upvotes: 1

Related Questions