1 2 3 4 5 6 7 8 9 10 11 12 13 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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
|
# frozen_string_literal: true
require 'active_support/core_ext/module/delegation'
module Enumerize
# Predicate methods.
#
# Basic usage:
#
# class User
# extend Enumerize
# enumerize :sex, in: %w(male female), predicates: true
# end
#
# user = User.new
#
# user.male? # => false
# user.female? # => false
#
# user.sex = 'male'
#
# user.male? # => true
# user.female? # => false
#
# Using prefix:
#
# class User
# extend Enumerize
# enumerize :sex, in: %w(male female), predicates: { prefix: true }
# end
#
# user = User.new
# user.sex = 'female'
# user.sex_female? # => true
#
# Use <tt>only</tt> and <tt>except</tt> options to specify what values create
# predicate methods for.
module Predicates
def enumerize(name, options={})
super
if options[:predicates]
Builder.new(enumerized_attributes[name], options[:predicates]).build(_enumerize_module)
end
end
class Builder
def initialize(attr, options)
@attr = attr
@options = options.is_a?(Hash) ? options : {}
end
def values
values = @attr.values
if @options[:only]
values &= Array(@options[:only]).map(&:to_s)
end
if @options[:except]
values -= Array(@options[:except]).map(&:to_s)
end
values
end
def names
values.map { |v| "#{v.tr('-', '_')}?" }
end
def build(klass)
warn_on_already_defined_methods
klass.delegate(*names, to: @attr.name, prefix: @options[:prefix], allow_nil: true)
end
def warn_on_already_defined_methods
names.each do |name|
method_name = [@options[:prefix], name].compact.join('_')
if @attr.klass.respond_to?(method_name)
warn(
"Predicate method `#{name}` is already defined as #{@attr.klass.name}##{name}. Use enumerize's :prefix option to avoid it"
)
end
end
end
end
end
end
|