rubyruby-datamapper

How to increment key values by power of two


I'm interested in storing multiple values in a single column, rather than use the traditional many-to-many table:

class Beer
  include DataMapper::Resource

  property :id, Serial
  property :name, String
  property :containers, Integer # use bit arithmetic to store multiple values

  validates_presence_of :name, :containers

end

class Container
  include DataMapper::Resource

  property :id, Serial # increment in powers of two?
  property :name, String
  property :volume, Integer

  validates_presence_of :name, :volume

end

Containers:

ID  Name    Volume  Unit
1   Growler 64      oz
2   Cowler  32      oz
4   Bomber  750     mL
8   Six-fifty  650  mL
16  4 pack  64      oz
32  6 pack  72      oz

Beers:

ID  Name Containers
1   LSD  72
2   Düo  16

Is there an easy way to configure a DataMapper resource to increment serial values in powers of 2? I'm assuming that the association is going to be a challenge.


Solution

  • You can't do that with Serial property type, but you can use an Integer and a before :create hook:

    class Container
      include DataMapper::Resource
    
      property :id, Integer, key: true # Use whatever options you like
      property :name, String
      property :volume, Integer
    
      validates_presence_of :name, :volume
    
      # Create a new id based on the last element
      before :create do |c|
        last_container = Container.last
        # If integer has N bits, then you can only store N containers in your database (normally, 32 or 64 bits).
        c.id = last_container ? (last_container.id * 2) : 1
      end
    end
    

    Anyways, you should be using the relational model, instead of using this hacky-tricks, as someone already commented on your post. It's much more maintainable, easy to read and simple than this kind of solutions.


    Oh, by the way, if you need fast access to your database, you should check a look at Graph databases and neo4jrb, an OGM for Neo4j.