Module: EnumX::DSL

Defined in:
lib/enum_x/dsl.rb

Overview

Mixin for any ActiveRecord or ActiveModel object to support enums.

Usage

First, make sure your model class includes EnumX::DSL:

include EnumX::DSL

Then, define any enum-like attribute using the #enum method. The best enum is always inferred. The following are identical:

enum :status, :statuses
enum :status, EnumX.statuses
enum :status, EnumX[:statuses]
enum :status

The latter infers the ‘statuses’ enum by default. If no applicable enum was found, an error is thrown.

Multi-enums

Specify the option :flags => true to allow the attribute to contain multiple enum values at once. The attribute will in essence become an array.

See Also:

Defined Under Namespace

Modules: ClassMethods Classes: FlagsSerializer, SingleSerializer

Class Method Summary collapse

Class Method Details

.define_mnemonics(target, attribute, enum) ⇒ Object

Mnemonics (single & multi)



349
350
351
352
353
354
355
356
357
# File 'lib/enum_x/dsl.rb', line 349

def self.define_mnemonics(target, attribute, enum)
  enum.values.each do |value|
    target.class_eval <<-RUBY, __FILE__, __LINE__+1
      def #{value}?
        :#{value} === #{attribute}
      end
    RUBY
  end
end

.define_multi_reader(target, attribute) ⇒ Object

Multi enum reader & writer



321
322
323
324
325
326
327
328
329
330
331
# File 'lib/enum_x/dsl.rb', line 321

def self.define_multi_reader(target, attribute)
  define_reader target, attribute, <<-RUBY
    enum = EnumX.find(self.class, :#{attribute.to_s})
    case value = %{read_value}
    when nil then nil
    when EnumX::ValueList then value
    when Enumerable then EnumX::ValueList.new(enum, value)
    else EnumX::ValueList.new(enum, [value])
    end
  RUBY
end

.define_multi_writer(target, attribute) ⇒ Object



333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/enum_x/dsl.rb', line 333

def self.define_multi_writer(target, attribute)
  define_writer target, attribute, <<-RUBY
    enum = EnumX.find(self.class, :#{attribute.to_s})
    value = case value
    when nil then nil
    when EnumX::ValueList then value
    when Enumerable then EnumX::ValueList.new(enum, value)
    else EnumX::ValueList.new(enum, [value])
    end
    %{write_value}
  RUBY
end

.define_reader(target, attribute, body) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Defines a generic attribute reader ActiveModel-like classes.



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/enum_x/dsl.rb', line 225

def self.define_reader(target, attribute, body)
  override = target.instance_methods.include?(attribute.to_sym)

  value_reader = case true
  when override
    "#{attribute}_without_enums"
  when target.instance_methods.include?(:read_attribute) || target.private_instance_methods.include?(:read_attribute)
    "read_attribute(:#{attribute})"
  else
    # We need a reader to fall back to.
    raise "cannot overwrite enum reader - no existing reader found"
  end

  body.gsub! '%{read_value}', value_reader

  if override
    target.class_eval <<-RUBY, __FILE__, __LINE__+1
      def #{attribute}_with_enums
        #{body}
      end
      alias_method_chain :#{attribute}, :enums
    RUBY
  else
    target.class_eval <<-RUBY, __FILE__, __LINE__+1
      def #{attribute}
        #{body}
      end
    RUBY
  end
end

.define_single_reader(target, attribute) ⇒ Object

Single enum reader & writer



293
294
295
296
297
298
299
300
301
302
303
# File 'lib/enum_x/dsl.rb', line 293

def self.define_single_reader(target, attribute)
  define_reader target, attribute, <<-RUBY
    case value = %{read_value}
    when EnumX::Value then value
    when nil then nil
    else
      enum = EnumX.find(self.class, :#{attribute.to_s.pluralize})
      enum[value] || value
    end
  RUBY
end

.define_single_writer(target, attribute) ⇒ Object



305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/enum_x/dsl.rb', line 305

def self.define_single_writer(target, attribute)
  define_writer target, attribute, <<-RUBY
    value = case value
    when EnumX::Value then value
    when nil then nil
    else
      enum = EnumX.find(self.class, :#{attribute.to_s.pluralize})
      enum[value] || value
    end
    %{write_value}
  RUBY
end

.define_writer(target, attribute, body) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Defines a generic attribute writer ActiveModel-like classes.



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
# File 'lib/enum_x/dsl.rb', line 258

def self.define_writer(target, attribute, body)
  method = :"#{attribute}="
  override = target.instance_methods.include?(method)

  value_writer = case true
  when override
    "self.#{attribute}_without_enums = value"
  when target.instance_methods.include?(:write_attribute) || target.private_instance_methods.include?(:write_attribute)
    "write_attribute :#{attribute}, value"
  else
    # We need a writer to fall back to.
    raise "cannot overwrite enum writer - no existing writer found"
  end

  body.gsub! '%{write_value}', value_writer

  if override
    target.class_eval <<-RUBY, __FILE__, __LINE__+1
      def #{attribute}_with_enums=(value)
        #{body}
      end
      alias_method_chain :#{attribute}=, :enums
    RUBY
  else
    target.class_eval <<-RUBY, __FILE__, __LINE__+1
      def #{attribute}=(value)
        #{body}
      end
    RUBY
  end
end

.included(target) ⇒ Object



30
31
32
# File 'lib/enum_x/dsl.rb', line 30

def self.included(target)
  target.extend ClassMethods
end