DataMapper many-to-many association

1.2k views Asked by At

At the moment I have the database model up and can populate the models with data:

   user.persons << person
    group.functions << function
    group.classificationlevels << clasfication
    user.groups << group

These are the models I am using at the moment for getting the data associated with each other:

module Core_authentication

  class User
    include DataMapper::Resource

    property :id, Serial
    property :username, String, :required => true, :unique => true  
    property :password, BCryptHash, :required => true 
    property :email, String, :format => :email_address, :required => true
    property :created_at, DateTime
    property :updated_at, DateTime

    #Creating join tables to link to group and person information
    has n, :persons, :through => Resource
    has n, :groups, :through => Resource

    def username= new_username
      super new_username.downcase
    end

  end 

  class Group
    include DataMapper::Resource

    property :id, Serial
    property :groupname, String, :required => true

    #Another jointable link group to link to functions and classification levels
    has n, :functions, :through => Resource
    has n, :classificationlevels, :through => Resource
    has n, :users, :through => Resource

    def groupname= new_group
      super new_group.downcase.capitalize!
    end
  end  

  class Person
    include DataMapper::Resource

    property :id, Serial
    property :firstname, String
    property :lastname, String, :required => true
    property :adress, String
    property :postcode, String, :length => 6, :required => true
    property :telefoon, String
    property :created_at, DateTime
    property :updated_at, DateTime

    has n, :users, :through => Resource

    def firstname= new_firstname
      super new_firstname.downcase.capitalize!
    end

    def lastname= new_lastname
      super new_lastname
    end

  end  

  class Function
    include DataMapper::Resource

    property :id, Serial
    property :name, String

    has n, :groups, :through => Resource

  end  

  class Classificationlevel
    include DataMapper::Resource

    property :id, Serial
    property :levelcode, Integer
    property :name, String

    has n, :groups, :through => Resource

  end

end

I want to get a user's groups they are a member of, and the classification level that is associated with each group.

I tried multiple ways of doing this, and also looked around on the web, but I cannot find a clear explanation on how I must do this, and so I can't get it working.

1

There are 1 answers

2
phillbaker On BEST ANSWER

The documentation for Datamapper (section for "Has, and belongs to, many (Or Many-To-Many)") has some hints, here's a simplified example of your models:

require 'sqlite3'
require 'dm-core'
require 'dm-sqlite-adapter'
require 'dm-migrations'

DataMapper.setup(:default, 'sqlite3:m2m.sqlite3')

class User
  include DataMapper::Resource
  property :id, Serial
  has n, :persons, :through => Resource # => PersonUser
  has n, :groups, :through => Resource # => GroupPerson
end

class Group
  include DataMapper::Resource
  property :id, Serial
  has n, :functions, :through => Resource # => FunctionGroup
  has n, :classificationlevels, :through => Resource # => GroupClassificationlevel
  has n, :users, :through => Resource # => GroupUser
end

class Person
  include DataMapper::Resource
  property :id, Serial
  has n, :users, :through => Resource # => PersonUser
end

class Function
  include DataMapper::Resource
  property :id, Serial
  has n, :groups, :through => Resource # => FunctionGroup
end

class Classificationlevel
  include DataMapper::Resource
  property :id, Serial
  has n, :groups, :through => Resource # => GroupClassificationlevel
end

And an example of using them (if you put both of these snippets in a file and run them, you can see the output):

DataMapper.finalize

DataMapper.auto_migrate!

user  = User.create
group = Group.create

# link them by adding to the relationship
user.groups << group
user.save

p user.groups # => [#<Group @id=1>]