Module: WithAttributes

Defined in:
lib/with_attributes.rb,
lib/with_attributes/version.rb

Constant Summary collapse

VERSION =
"0.1.0".freeze

Instance Method Summary collapse

Instance Method Details

#with_attribute(*attrs, default: true) ⇒ Object

Raises:

  • (ArgumentError)


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
# File 'lib/with_attributes.rb', line 4

def with_attribute(*attrs, default: true)
  raise ArgumentError, "invalid with_attribute default option" unless [true, false].include?(default)

  attrs.each do |attr|
    raise NameError, "invalid with_attribute name: #{attr}" unless /^[_A-Za-z]\w*$/.match?(attr)

    class_eval(<<~CODE, __FILE__, __LINE__ + 1)
      def self.#{attr}?
        value = Thread.current["with_attribute_#{attr}_\#{object_id}"]

        if value.nil?
          if superclass.respond_to?(:#{attr}?)
            superclass.#{attr}?
          else
            #{default}
          end
        else
          value
        end
      end

      def self.with_#{attr}
        current = Thread.current["with_attribute_#{attr}_\#{object_id}"]
        enable_#{attr}
        yield if block_given?
      ensure
        Thread.current["with_attribute_#{attr}_\#{object_id}"] = current
      end

      def self.without_#{attr}
        current = Thread.current["with_attribute_#{attr}_\#{object_id}"]
        disable_#{attr}
        yield if block_given?
      ensure
        Thread.current["with_attribute_#{attr}_\#{object_id}"] = current
      end

      def self.enable_#{attr}
        Thread.current["with_attribute_#{attr}_\#{object_id}"] = true
      end

      def self.disable_#{attr}
        Thread.current["with_attribute_#{attr}_\#{object_id}"] = false
      end

      def #{attr}?
        @#{attr}.nil? ? self.class.#{attr}? : @#{attr}
      end

      def with_#{attr}
        current = @#{attr}
        enable_#{attr}
        yield if block_given?
      ensure
        @#{attr} = current
      end

      def without_#{attr}
        current = @#{attr}
        disable_#{attr}
        yield if block_given?
      ensure
        @#{attr} = current
      end

      def enable_#{attr}
        @#{attr} = true
      end

      def disable_#{attr}
        @#{attr} = false
      end
    CODE
  end
end