Skip to content

galaxycats/haz_enum

Repository files navigation

haz_enum

haz_enum is a ActiveRecord extension to allow associations to enumerations.

Installation

haz_enum is hostet on rubygems.org, so yoou can just do

gem install haz_enum

or if you use bundler, just add the following line to your Gemfile:

gem "haz_enum"

Example with renum

renum is a perfect library for enumerations in ruby (see github.com/duelinmarkers/renum). Here is a simple renum definition:

enum :Roles do
  Admin()
  Supervisor()
  ContentManager()
end

in your AR-model you can now write

class User < ActiveRecord
  has_enum :role
end

what you need is a column in your db named role with type string.

user = User.create(:role => Roles::Admin)
user.has_role?(Roles::Admin) => true
user.has_role?(Roles::Supervisor) => false

The example above realizes one role per user. But what if you want to have multiple Roles per user? Just change has_enum to has_set and rename the column to roles:

class User < ActiveRecord
  has_set :roles
end

user = User.create(:roles => Roles::Admin)
user.has_role?(Roles::Admin) => true
user.has_role?(Roles::Supervisor) => false

or

user = User.create(:roles => [Roles::Admin, Roles::Supervisor])
user.has_role?(Roles::Admin) => true
user.has_role?(Roles::Supervisor) => true

now roles behaves just like an array, so you can also do

user = User.create(:roles => Roles::Admin)
user.roles << Roles::Supervisor
user.has_role?(Roles::Admin) => true
user.has_role?(Roles::Supervisor) => true

Using bitfields

If you have an enum with many possible values you can switch from :yml to field_type :bitfield.

class User < ActiveRecord
  has_set :roles, :field_type => :bitfield
end

Your db-column has to be an integer for field_type bitfield. If you use mysql with int(11) you are able to have up to 64 different values in your enumeration.

You do not need renum

…but it really makes sense to use this library. If you really do not want to use it you have to implement against an interface. Here is a simple ruby module example to get the same results as above for has_enum:

module Roles
  class Admin; def self.name; "Admin"; end; end
  class Supervisor; def self.name; "Supervisor"; end; end
  class ContentManager; def self.name; "ContentManager"; end; end
end

You cannot use this for has_set and field_type :yml since you cannot dump anonymous classes. But you can use field_type :bitfield. Then your class could look something like that:

module Roles
  class Admin
    def self.bitfield_index; 1; end
  end
  class Supervisor
    def self.bitfield_index; 2; end
  end
  class ContentManager
    def self.bitfield_index; 3; end
  end
  class <<self
    def values
      Roles.constants.collect { |c| Roles.const_get(c) }
    end
  end
end

As you can see, your classes have to respond to bitfield_index and your wrapping module has to respond to values and return all available classes. So now you could do:

class User < ActiveRecord
  has_enum :role, :field_type => :bitfield
end

Note on Patches/Pull Requests

  • Fork the project.

  • Make your feature addition or bug fix.

  • Add tests for it. This is important so I don’t break it in a future version unintentionally.

  • Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)

  • Send me a pull request. Bonus points for topic branches.

Copyright © 2010 Galaxy Cats IT Consulting GmbH. See LICENSE for details.

About

has_set and has_enum for ActiveRecord

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages