rubysinatradatamapperruby-datamapper

Boolean vs. Enum vs. Flag


I am working on a website that allows users to login. All users have 1 account, an account can have many orders. A user may be a client, worker, or manager. A client is never a worker nor a manager. a manager is also a worker. I would like to present additional sections of pages/ navigation options depending on the type of user logged in.

Currently I am using a set of boolean values to mark the user as a specific type, test for that value, and run through some if/elsif blocks to generate the page that the user sees.

class User
  include DataMapper::Resource
  # ...
  # various properties
  # ...
  property :client, Boolean
  property :worker, Boolean
  property :manager, Boolean
end

And then I am using a before filter to test for the user type and set the result as variable.

before do
  @user = session[:user]
  if @user.client?
    @ura = 'client'
  elsif @user.worker?
    @ura = 'worker'
  elseif @user.manager?
    @ura = 'manager'
  end
end

Then in my views I have @ura to play around with. It seems to me that this is already going to cause me problems for managers because @ura will have to be both worker & manager. I could use some or's in my views but I think a better solution would to have the user type set as an Enum or Flag. But I don't really understand how to use that in my process.

I would like to know what the advantages/disadvantages of each are & a basic example of how I can end up with an appropriate value in @ura.


Solution

  • I don't remember how I solved this exact issue ( I think it was for a bicycle delivery app ), but today just noticed that it is still unanswered.

    So, just shy of a decade later, even though I no longer use DataMapper regularly, he is how I would solve this now;

    At the time I did not understand fully the difference between authentication & authorization with respect to a users's Role in a system.

    class User
      include DataMapper::Resource
      ...
      properties
      ...
      property :role, Enum[ :client, :worker, :manager ]
    end
    
    class Employee < User
      include DataMapper::Resource
      ...
       more properties
    end
    

    This way all users can have the things they need, employees could be further split into Worker & Manager. then you can put the appropriate validations on the corresponding model. More code upfront but more maintainable & more easy to scale, just add a new role to the User Enum & a corresponding class.

    If the class doesn't do anything beyond namespace/logical separation you might even be able to get away with some meta programing/reflection infer the classes from the enum & include appropriate modules at initialization.