Class: Module

Inherits:
Object show all
Defined in:
lib/utilrb/module/include.rb,
lib/utilrb/module/ancestor_p.rb,
lib/utilrb/module/cached_enum.rb,
lib/utilrb/module/is_singleton.rb,
lib/utilrb/module/define_method.rb,
lib/utilrb/module/dsl_attribute.rb,
lib/utilrb/module/attr_predicate.rb,
lib/utilrb/module/attr_enumerable.rb,
lib/utilrb/module/define_or_reuse.rb,
lib/utilrb/module/singleton_class_p.rb,
lib/utilrb/module/const_defined_here_p.rb

Instance Method Summary collapse

Instance Method Details

#__include_single_module(mod) ⇒ Object



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
# File 'lib/utilrb/module/include.rb', line 22

def __include_single_module(mod)
  if mod.const_defined?(:ModuleExtension)
 if is_a?(Module)
    unless const_defined?(:ModuleExtension)
  const_set(:ModuleExtension, Module.new)
    end
    const_get(:ModuleExtension).class_eval do
  __instance_include__ mod.const_get(:ModuleExtension)
    end
    extend mod.const_get(:ModuleExtension)
 end
        # Do nothing on classes
  end
  if mod.const_defined?(:ClassExtension)
 if !is_a?(Class)
    unless const_defined?(:ClassExtension)
  const_set(:ClassExtension, Module.new)
    end
    const_get(:ClassExtension).class_eval do
  __instance_include__ mod.const_get(:ClassExtension)
    end
 else
    extend mod.const_get(:ClassExtension)
 end
  end

  __instance_include__ mod
end

#attr_enumerable(name, attr_name = name, enumerator = :each, &init_block) ⇒ Object

Support for attributes that are enumerables. This methods defines two methods:

obj.attr_name # => enumerable
obj.each_name(key = nil) { |value| ... } # => obj

The first one returns the enumerable object itself. The second one iterates on the values in attr_name. If key is not nil, then #attr_name is supposed to be a hash of enumerables, and key is used to select the enumerable to iterate on.

The following calls are equivalent

obj.attr_name.each { |value| ... }
obj.each_name { |value| ... }

And these two are equivalent:

obj.attr_name[key].each { |value| ... }
obj.each_name(key) { |value| ... }

enumerator is the name of the enumeration method we should use. init_block, if given, should return the value at which we should initialize #attr_name.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/utilrb/module/attr_enumerable.rb', line 25

def attr_enumerable(name, attr_name = name, enumerator = :each, &init_block)
  class_eval do
 attribute(attr_name, &init_block)
  end
    class_eval "        def each_\#{name}(key = nil, &iterator)\n            return unless \#{attr_name}\n            if key\n                \#{attr_name}[key].\#{enumerator}(&iterator)\n            else\n                \#{attr_name}.\#{enumerator}(&iterator)\n            end\n    self\n        end\n    EOF\nend\n", __FILE__, __LINE__+1

#attr_predicate(name, writable = false) ⇒ Object

Defines a name? predicate, and if writable is true a #name= method. Note that name can end with ‘?’, in which case the ending ‘?’ is removed.

The methods use the @name instance variable internally



7
8
9
10
11
12
13
14
15
16
# File 'lib/utilrb/module/attr_predicate.rb', line 7

def attr_predicate(name, writable = false)
  attr_name = name.to_s.gsub(/\?$/, '')
  attr_reader attr_name
  alias_method "#{attr_name}?", attr_name
  remove_method attr_name

  if writable
 class_eval "def #{attr_name}=(value); @#{attr_name} = !!value end", __FILE__, __LINE__+1
  end
end

#cached_enum(enum_name, name, with_arg) ⇒ Object

Creates enum_#{name} method which returs an Enumerator object for the each_#{enum_name} method. This enumerator is created once.

If with_arg is true, it is supposed that the ‘each_’ method requires one argument, which is given in argument of the ‘enum’ method. In that case, an enumerator is created for each argument



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/utilrb/module/cached_enum.rb', line 21

def cached_enum(enum_name, name, with_arg)
    include CachedValuesSupport
  if with_arg
 class_eval "    def enum_\#{name}(arg)\n  @enum_\#{name} ||= Hash.new\n                cached_variables << :@enum_\#{name}\n  @enum_\#{name}[arg] ||= enum_for(:each_\#{enum_name}, arg)\n    end\n    EOD\n  else\n class_eval <<-EOD, __FILE__, __LINE__+1\n    def enum_\#{name}\n                cached_variables << :@enum_\#{name}\n  @enum_\#{name} ||= enum_for(:each_\#{enum_name})\n    end\n    EOD\n  end\nend\n", __FILE__, __LINE__+1

#const_defined_here?(name) ⇒ Boolean

Returns:

  • (Boolean)


3
4
5
# File 'lib/utilrb/module/const_defined_here_p.rb', line 3

def const_defined_here?(name)
    const_defined?(name, false)
end

#define_method_with_block(name, &mdef) ⇒ Object

Emulate block-passing by converting the block into a Proc object and passing it to the given block as last argument dule)

For instance

define_method('my_method') do |a, &block|
end

Is written as define_method_with_block(‘my_method’) do |block, a| end

The block is given first to allow the following construct:

define_method_with_block(‘my_method’) do |block, *args| end

block is nil if no block is given during the method call



21
22
23
24
25
26
27
28
# File 'lib/utilrb/module/define_method.rb', line 21

def define_method_with_block(name, &mdef)
  class_eval " def \#{name}(*args, &block)\n    dmwb_\#{name}_user_definition(block, *args) \n end\n  EOD\n  define_method(\"dmwb_\#{name}_user_definition\", &mdef)\nend\n", __FILE__, __LINE__+1

#define_or_reuse(name, value = nil) ⇒ Object

:call-seq

define_or_reuse(name, value)   ->              value
define_or_reuse(name) { ... }  ->              value

Defines a new constant under a given module, or reuse the already-existing value if the constant is already defined.

In the first form, the method gets its value from its argument. In the second case, it calls the provided block



12
13
14
15
16
17
18
19
20
# File 'lib/utilrb/module/define_or_reuse.rb', line 12

def define_or_reuse(name, value = nil)
    if const_defined_here?(name)
        const_get(name)
    else
        module_eval do
            const_set(name, (value || yield))
        end
    end
end

#dsl_attribute(*names, &filter_block) ⇒ Object

call-seq:

dsl_attribute(name)
dsl_attribute(name,name2,name3)
dsl_attribute(name) { |value| ... }

This defines a name instance method on the given class which accepts zero or one argument

Without any argument, it acts as a getter for the @name attribute. With one argument, it acts instead as a setter for the same attribute and returns self. If a block has been given to dsl_attribute, any new value is passed to the block, whose return value is actually saved in the instance variable. This block can therefore both filter the value (convert it to a desired form) and validate it.

The goal of this method is to have a nicer way to handle attribute in DSLs: instead of

model = create_model do
 self.my_model_attribute = 'bla'

 if (my_model_attribute)

<do something>

   end
end

(or worse, using set_ and get_ prefixes), we can do

model = create_model do
 my_model_attribute 'bla', arg0, arg1, ...

 if (my_model_attribute)

<do something>

   end
end


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
# File 'lib/utilrb/module/dsl_attribute.rb', line 37

def dsl_attribute(*names, &filter_block)
    if names.size > 1 && filter_block
        raise ArgumentError, "multiple names as argument are only supported if no block is given"
    end
    names.each do |name|
  class_eval do
        if filter_block
            define_method("__dsl_attribute__#{name}__filter__", &filter_block)
        end

 define_method(name) do |*value|
    if value.empty?
  instance_variable_get("@#{name}")
    elsif filter_block
                if filter_block.arity >= 0 && value.size != filter_block.arity
                    raise ArgumentError, "too many arguments. Got #{value.size}, expected #{filter_block.arity}"
                end

  filtered_value = send("__dsl_attribute__#{name}__filter__", *value)
  instance_variable_set("@#{name}", filtered_value)
  self
    else
                if value.size == 1
                    instance_variable_set("@#{name}", value.first)
                else
                    instance_variable_set("@#{name}", value)
                end
  self
    end
 end
  end
    end
end

#has_ancestor?(klass) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


2
3
4
# File 'lib/utilrb/module/ancestor_p.rb', line 2

def has_ancestor?(klass) # :nodoc:
    self <= klass
end

#include(*mods) ⇒ Object

Includes a module in this one, with support for class extensions

If a module defines a ClassExtension submodule, then

  • if it is included in a module, the target’s ClassExtension module includes the source ClassExtension (and if there is no ClassExtension in the target, it is created)

  • if it is included in a Class, the ClassExtension module extends the class.



16
17
18
19
20
# File 'lib/utilrb/module/include.rb', line 16

def include(*mods)
    mods.each do |mod|
        __include_single_module(mod)
    end
end

#is_singleton?Object



5
# File 'lib/utilrb/module/is_singleton.rb', line 5

alias :is_singleton? :singleton_class?

#singleton_class?Boolean

It so happens that this method to determine whether a class is a singleton class is valid for ruby 2.0 and breaks on 2.1 … However (!) on 2.1 singleton_class? is defined

Returns:

  • (Boolean)


6
7
8
9
10
11
12
# File 'lib/utilrb/module/singleton_class_p.rb', line 6

def singleton_class?
    if instance_variable_defined?(:@__utilrb_singleton_class)
        @__utilrb_singleton_class
    else
        @__utilrb_singleton_class = (ancestors.first != self)
    end
end