On Jan 31, 2006, at 11:39 AM, Harvey B. wrote:
using acts_as_authenticated as a starting point? If so, would you
mind
letting me have a look at some code?
Any help would be much appreciated as I am a newbie.
Regards
Harvey
Harvey-
I added acts_as_tree to the acts_as_authenticated user model. Then I
add a role column to the user database table as well as the parent_id
column required by acts_as_tree. This allows me to have a user system
with roles that inherit from each other.
What I mean is that the user role systems is a tree. So the main
root superuser that you first create is the ‘root’ user or main
admin. You can then create, say sub admins under the root user and
moderator users under the root user. Then normal users go underneath
the subadmin or moderator, however you want to refer to it. This ends
up being pretty easy to implement. If you are interested contact me
off list and I can send you parts of the app. It’s an employee review
system for the newspaper I work for. So the publisher is the head of
all. And then there are directors under him and managers under
directors and employees under managers. This way no one can see back
up the tree. Each user in the tree can only edit and view users or
content created by themselves or users underneath them in the tree.
So here is the schema for the user table to use with
acts_as_authenticated:
create_table “users”, :force => true do |t|
t.column “login”, :integer, :limit => 6
t.column “email”, :string, :limit => 100
t.column “crypted_password”, :string, :limit => 40
t.column “salt”, :string, :limit => 40
t.column “activation_code”, :string, :limit => 40
t.column “activated_at”, :datetime
t.column “created_at”, :datetime
t.column “updated_at”, :datetime
t.column “active”, :boolean, :default => false
t.column “role”, :string, :limit => 20
t.column “parent_id”, :integer
t.column “first_name”, :string, :limit => 30
t.column “last_name”, :string, :limit => 30
t.column “users_count”, :integer, :default => 0, :null => false
end
Then i add acts_as_tree and any relations to the user model:
class User < ActiveRecord::Base
has_many :reviews
acts_as_tree :order => “role”, :counter_cache => true
#…
end
Then I use /user/signup only for the first root user. After that, a
user with rights to create subusers has to use the add_user action:
in user_controller.rb or account_controller.rb or whatever you
named your user controller.
def add_user
return unless request.post?
@parent = User.find(session[:user_id])
if @parent.children.create(params[:user])
redirect_back_or_default :controller => ‘dashboard’, :action
=> @parent.role.downcase
flash[:notice] = “Thanks for signing up!”
end
end
Notice that I redirect back to :controller => 'dashboard', :action
=> @parent.role.downcase. The dashboard is where you manage users
beneath you. and the @parent.role.downcase is the name of an action
in the dashboard_controller that matches the role of the user. So if
the @parent.role is ‘Publisher’, they will be redirected to /
dashboard/publisher. This scheme works out great for me and is pretty
simple to set up and customize. Its not the best if you need to have
a ton of roles but for less then 5-10 roles this works great.
Here is a helper method that will print out nested unordered lists
of all the users underneath your user in the tree and link to them or
whatever:
module ApplicationHelper
def find_all_children(parent)
if parent.children.size > 0
ret = ‘
’
parent.children.each { |child|
if child.children.size > 0
ret += ‘- ’
ret += link_to “#{child.role}: #{child.last_name}, #
{child.first_name} : #{child.login}”,
:controller => ‘review’, :action =>
‘boss_view’, :id => child
ret += find_all_children(child)
ret += ‘ ’
else
ret += ‘- ’
ret += link_to “#{child.role}: #{child.last_name}, #
{child.first_name} : #{child.login}”,
:controller => ‘review’, :action =>
‘boss_view’, :id => child
ret += ‘ ’
end
}
ret += ‘
’
end
end
end
Keep in mind that this is a recursive method. If you don't set up
the counter_cache correctly in your user model it will issue a ton of
COUNT sql statements while it goes down the list of children users.
So make sure to set up a counter cache in the user model. The model
and schema above have this set up for you. Let me know how it goes. I
am thinking of adding this as an add on the the acts_as_authenticated
but its actually very little code so I may just keep it simple. Its a
bit app specific because of the roles and whatever your app needs so
keep that in mind.
Cheers-
-Ezra Z.
Yakima Herald-Republic
WebMaster
509-577-7732
[email protected]