Module: ScopedEnum::ClassMethods

Defined in:
lib/scoped_enum.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extended(base) ⇒ Object



9
10
11
12
# File 'lib/scoped_enum.rb', line 9

def self.extended(base)
  base.class_attribute(:defined_enum_scopes)
  base.defined_enum_scopes = HashWithIndifferentAccess.new
end

Instance Method Details

#scoped_enum(enum_name, enum_entries, scopes = {}) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/scoped_enum.rb', line 14

def scoped_enum(enum_name, enum_entries, scopes = {})
  enum(enum_name => enum_entries)
  scopes = HashWithIndifferentAccess.new_from_hash_copying_default(scopes)

  target_enum = defined_enums[enum_name.to_s]
  scopes.each do |scope_name, scope_enum_keys|
    sub_enum_values = target_enum.values_at(*scope_enum_keys)
    if defined_enum_scopes.has_key?(scope_name)
      fail ArgumentError,
           "Conflicting scope names. A scope named #{scope_name} has already been defined"
    elsif sub_enum_values.include?(nil)
      unknown_key = scope_enum_keys[sub_enum_values.index(nil)]
      fail ArgumentError, "Unknown key - #{unknown_key} for enum #{enum_name}"
    elsif respond_to?(scope_name.to_s.pluralize)
      fail ArgumentError,
           "Scope name - #{scope_name} conflicts with a class method of the same name"
    elsif instance_methods.include?("#{scope_name}?".to_sym)
      fail ArgumentError,
           "Scope name - #{scope_name} conflicts with the instance method - #{scope_name}?"
    end

    sub_enum_entries = target_enum.slice(*scope_enum_keys)
    defined_enum_scopes[scope_name] = sub_enum_entries

    # 1. Instance method <scope_name>?
    define_method("#{scope_name}?") do
      sub_enum_entries.include? self.role
    end

    # 2. The class scope with the scope name
    scope scope_name.to_s.pluralize, -> { where("#{enum_name}" => sub_enum_entries.values) }
  end
  # 3. The class method to return all scopes of the enum
  singleton_class.send(:define_method, "#{enum_name}_scopes") { defined_enum_scopes.slice(*scopes.keys) }
end