pluginaweek / attribute_predicates

Adds automatic generation of predicate methods when defining attributes

This URL has Read+Write access

attribute_predicates / lib / attribute_predicates / extensions / module.rb
100644 82 lines (77 sloc) 2.56 kb
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
module PluginAWeek #:nodoc:
  module AttributePredicates
    module Extensions
      # Adds support for automatically defining predicate methods using +attr_predicate+
      # when defining attributes using +attr+, +attr_reader+, +attr_reader+, and
      # +attr_accessor+.
      #
      # == Examples
      #
      # The predicate methods for attributes checks whether the value is blank?
      # for determining whether true or false should be returned. For example,
      #
      # class Person
      # attr_accessor :value
      # end
      #
      # p = Person.new
      # p.value = false
      # p.value? # => false
      #
      # p.value = true
      # p.value? # => true
      #
      # p.value = []
      # p.value? # => false
      #
      # p.value = [false]
      # p.value? # => true
      module Module
        def self.included(base) #:nodoc:
          base.class_eval do
            %w(attr attr_reader attr_writer attr_accessor).each do |method|
              alias_method "#{method}_without_predicates", method
              alias_method method, "#{method}_with_predicates"
            end
          end
        end
        
        # Defines a predicate method, using +attr_predicate+, in addition to the
        # attribute accessors. For example,
        #
        # module Mod
        # attr :is_okay
        # end
        #
        # Mod.instance-methods.sort # => ["is_okay", "is_okay?"]
        def attr_with_predicates(*args)
          attr_without_predicates(*args)
          attr_predicate(args.first)
        end
        
        [:attr_reader, :attr_writer, :attr_accessor].each do |method|
          define_method("#{method}_with_predicates") do |*symbols|
            send("#{method}_without_predicates", *symbols)
            symbols.each {|symbol| attr_predicate(symbol)}
          end
        end
        
        private
          # Returns true if the specified variable is not blank, otherwise false
          def attr_predicate(symbol)
            define_method("#{symbol}?") do
              value = instance_variable_get("@#{symbol}")
              if value.respond_to?(:blank?)
                # Use ActiveSupport's implementation
                !value.blank?
              elsif value.respond_to?(:empty?)
                !value.empty?
              else
                !!value
              end
            end
          end
      end
    end
  end
end
 
::Module.class_eval do
  include PluginAWeek::AttributePredicates::Extensions::Module
end