module SimpleSet::ClassMethods
Public Instance Methods
Provides ability to create simple sets based on hashes or arrays, backed by integer columns (but not limited to integer columns).
Columns are supposed to be suffixed by _cd
, if not, use :column => 'the_column_name'
, so some example migrations:
add_column :users, :roles_cd, :integer add_column :users, :permissions, :integer # and a custom column...
and then in your model:
class User as_set :roles, [:management, :accounting] end # or use a hash: class User as_set :user_permissions, { create_invoice: 1, send_invoice: 2, create_user: 4, all: 7 }, column: 'permissions' end
Now it’s possible to access the set and the internally stored value like:
john_doe = User.new john_doe.roles #=> [] john_doe.roles = [:accounting] john_doe.roles #=> [:accounting] john_doe.roles_cd #=> 2
And to make life a tad easier: a few shortcut methods to work with the set are also created.
john_doe.accounting? #=> true john_doe.accounting = false john_doe.accounting? #=> false
Configuration options:¶ ↑
-
:column
- Specifies a custom column name, instead of the default suffixed_cd
column. -
:prefix
- Define a prefix, which is prefixed to the shortcut methods (e.g.<symbol>=
and<symbol>?
), if it’s set totrue
the enumeration name is used as a prefix, else a custom prefix (symbol or string) (default isnil
=> no prefix) -
:slim
- If set totrue
no shortcut methods for all enumeration values are being generated, if set to:class
only class-level shortcut methods are disabled (default isnil
=> they are generated) -
:whiny
- Boolean value which if set totrue
will throw anArgumentError
if an invalid value is passed to the setter (e.g. a value for which no enumeration exists). if set tofalse
no exception is thrown and the internal value is left untouched (default istrue
)
# File lib/simple_set.rb, line 75 def as_set(set_cd, values, options = {}) options = SimpleSet.default_options.merge({column: "#{set_cd}_cd"}).merge(options) options.assert_valid_keys(:column, :prefix, :slim, :whiny) metaclass = (class << self; self; end) values = SimpleSet::SetHash.new(values) define_method("#{set_cd}") do current = send(options[:column]) return nil if current.nil? values.select { |k,v| v == current & v }.keys end define_method("#{set_cd}=") do |new_values| real = nil if ! new_values.nil? then new_values = new_values.reject { |x| x == ''}.collect { |x| x.to_sym } real = new_values.collect do |k| if values.has_key?(k) then values[k] else raise(ArgumentError, "Invalid set value : #{k}") if options[:whiny] 0 end end.inject(:|) end send("#{options[:column]}=", real) end metaclass.send :define_method, "#{set_cd}" do return values.keys end if options[:slim] != true then prefix = options[:prefix] && "#{options[:prefix] == true ? set_cd.to_s.singularize : options[:prefix]}_" values.each do |k,code| sym = k.to_sym define_method("#{prefix}#{sym}?") do current = send(options[:column]) || 0 code == (code & current) end define_method("#{prefix}#{sym}=") do |value| current = send(options[:column]) || 0 if value then current |= code else current &= ~code end send("#{options[:column]}=", current) code == (current & code) end unless options[:slim] == :class then metaclass.send(:define_method, "#{prefix}#{sym}", Proc.new { |*args| args.first ? k : code }) end end end end