Topic: data modelling for beginners

Hi,

I'm new to rails and got some problems how i should design my models and relations the "rails way".

I've got the following Models:
User
Group
Item
ItemGroup
Rights

relations:
User habtm  Groups
User has many Items
Item habtm ItemGroups

Group is set up as "acts_as_nested_set" so i can have subgroups and stuff..
thats the easy way :-))

Where the problems start is with the rights on items:

a User can have different rights on a item.
also a Group can have rights on a single item
then a User can also have rights on a ItemGroup (say rights on items through ItemGroups)
so can a Group have rights on ItemGroups...

hope this makes sense and it's understandable... sorry for the bad english.. my native language is german.

anyway, the question is... how can I implement the "Right" model with its relations in a proper way?
do i have to setup multiple Right models (inheritance)? or can i handle that somehow with polymorphic associations?


cheers,
maze

Re: data modelling for beginners

First of all, what exactly does the Right model contain? Does it contain "can_destroy", "can_update" kind of boolean columns? Is it used to determine what a given user/group can do to an item/item group?

Railscasts - Free Ruby on Rails Screencasts

Re: data modelling for beginners

My current project has a similar User-Group-Rights Model.

We have created a link between Users and Usergroups with HABTM. Our User model also has a has_many relationship to our usergroup_permission model (it works like your Rights table).

Our usergroup_permission model belongs_to user and attribute_group models. Attribute Groups is like your Items. It is the table that we want to assign permissions to.

Finally our attribute_group model belongs_to our usergroup_permission model.

The permissions table schema looks like:

  create_table "usergroup_permissions", :force => true do |t|
    t.column "attributegroup_id", :integer
    t.column "usergroup_id",      :integer
    t.column "create_perm",       :boolean
    t.column "read_perm",         :boolean
    t.column "update_perm",       :boolean
    t.column "delete_perm",       :boolean
  end

We are only assigning permissions for a user_group to do something to a single attribute_group. 

I think you would need a similar Rights table between Users and Items, Groups and Items, Users and ItemGroups, Groups and ItemGroups. The HABTM relationship between Users and Groups will assign a user to a group. The HABTM relationship between Items and Itemgroups will assign an item to a group.

Ich weiss nichts ob diese ist richtig fur dein Problem. Es funktioniert ganz gut fur mein Projekt und die Ideen sind richtig.

Also, dein Englisch ist gut. So gut wie mein Deutsch! Haha!

Re: data modelling for beginners

ryanb wrote:

First of all, what exactly does the Right model contain? Does it contain "can_destroy", "can_update" kind of boolean columns? Is it used to determine what a given user/group can do to an item/item group?

hi and thanks for the fast replies!

ryanb, yes the Right model contains "can_read, can_write, can_destroy and can_bequeath". And all these rights refer on Items.


jbartels, thanks for the answer. I'll have a look at it. But on the first glimpse it looks like I would need about 4 Rights model to implement my application model. And I think there must be a better (DRY) way to do it.

Gr

Re: data modelling for beginners

I think polymorphic association is the way to go. I'm still not entirely clear on the schema, but see if this works for you:

class User < ActiveRecord::Base
  belongs_to :right
end

class Group < ActiveRecord::Base
  belongs_to :right
end

class Right < ActiveRecord::Base
# columns:
# - item_id
# - item_type 
  has_many :users
  has_many :groups
  belongs_to :item, :polymorphic => true
end

class ItemGroup < ActiveRecord::Base
  has_many :rights, :as => :item
end

class Item < ActiveRecord::Base
  has_many :rights, :as => :item
end


I don't think this is quite right (do you want to make a separate Right model for each item/item group?) But, it may give you some ideas, or you can specify what won't work with this schema and I'll try to come up with something else.

Railscasts - Free Ruby on Rails Screencasts

Re: data modelling for beginners

I started with some first implementations. I changed some Model names so it makes more sense.

my Models look like that:

class User < ActiveRecord::Base
  has_many :rights
  has_and_belongs_to_many :groups
  has_many :credentials, :through => :rights
end

class Group < ActiveRecord::Base
  has_many :rights, as :user
  has_and_belongs_to_many :users
end

class Credential < ActiveRecord::Base
  has_many :rights
  belongs_to :user
  has_and_belongs_to_many :credentialgroups
end

class CredentialGroup < ActiveRecord::Base
  has_and_belongs_to_many :credentials
end

class Right < ActiveRecord::Base
  belongs_to :user, :polymorphic => true
  belongs_to :credential
end


it is possible to find credentials if there is a link via the Rights Model: User.credentials
it is also possible to give rights on a credential to an other user.

now I want to assign rights on a credential to a Group. All the Users in the Group should inherit the rights on the credential from the group.

and I also want to create CredentialGroups and assign rights to a CredentialGroup which then apply to all Credentials in this Group.

But If I change the rights class like in the following code, i get an error when trying to get "user.credentials" The error says "Cannot have has_many :through association on the polymorphic object"

class Right < ActiveRecord::Base
  belongs_to :user, :polymorphic => true
  belongs_to :credential, :polymorphic => true
end

So, I think I'm on the wrong way :-(

Re: data modelling for beginners

Interesting, seems you have a use for double polymorphic association mentioned in this thread.

As for your problem with has_many :through and polymorphic association, see this article for a solution. At least I think it will work in your case.

Railscasts - Free Ruby on Rails Screencasts