Question

I'm very new to DataMapper, and I'm trying to create models for the following scenario:

I've got a number of users (with a user name, password etc.), who can also be players or referees or both (so Single Table Inheritance is not an option). The base models would be:

class User
  include DataMapper::Resource
  property :id, Serial
  # Other user properties go here  
end

class Player
  include DataMapper::Resource
  property :id, Serial
  # Other player properties go here
  # Some kind of association goes here
end

class Referee
  include DataMapper::Resource
  property :id, Serial
  # Other referee properties go here
  # Some kind of association goes here
end

DataMapper.finalize

I'm not sure, though, what kinds of associations to add to Player and Referee. With belongs_to :user, multiple players can be associated with the same user, which doesn't make sense in my context. In RDBMS terms I guess what I want is a unique constraint on the foreign key in the Players and Referees tables.

How do I accomplish this in my DataMapper model? Do I have to perform the check myself in a validation?

Was it helpful?

Solution

There are different ways you could do this. Here's one option:

class User
  include DataMapper::Resource
  property :id, Serial
  # Other properties...
  has 1, :referee, :required => false
  has 1, :player, :required => false
end

class Referee
  include DataMapper::Resource
  # DON'T include "property :id, Serial" here
  # Other properties...
  belongs_to :user, :key => true
end
class Player
  include DataMapper::Resource
  # DON'T include "property :id, Serial" here
  # Other properties...
  belongs_to :user, :key => true
end

Act on the referee/player models like:

u = User.create(...)
u.referee = Referee.create(...)
u.player = Player.create(...)

u.player.kick_ball() # or whatever you want to call
u.player.homeruns
u.referee.flag_play() # or whatever.

See if this works. I haven't actually tested it but it should be good.

OTHER TIPS

The previous answer works other than :required => false is not recognized for has 1 properties.

It's also confusing because for has n properties, you can use new right on the property or otherwise treat it as a collection. In your example, you would be tempted to code

u = User.create ...
u.referee.create ...

But that fails in the case of has 1 because the property is a single value, which begins life as nil and so you have to use the method the previous answer indicates. Also, having to explicitly make the belongs_to association into the key is a little confusing.

It does seem to execute validations and have the right association actions (so u.save will also save the referred-to Referee). I just wish it were more consistent between has n and has 1.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top