craig craig - 5 months ago 13
Ruby Question

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.

Answer

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.