Class: Module

Inherits:
Object show all
Defined in:
lib/nrser/core_ext/module/names.rb,
lib/nrser/core_ext/module/method_objects.rb,
lib/nrser/core_ext/module/source_locations.rb

Overview

Extension methods for Module

{Method} Object Readers collapse

Source Location Readers collapse

Instance Method Summary collapse

Instance Method Details

#canonical_rel_pathnil, Pathname

TODO:

I bet ActiveSupport has some method for this re auto-loading.

Get the “canonical” lib-relative path for this module based off it’s #name (via String#underscore, with ‘’.rb’‘ suffixed).

Returns:

  • (nil)

    If this module is #anonymous?.

  • (Pathname)

    If this module is not #anonymous?.



159
160
161
162
163
164
165
# File 'lib/nrser/core_ext/module/source_locations.rb', line 159

def canonical_rel_path
  if anonymous?
    nil
  else
    Pathname.new( name.underscore + '.rb' )
  end
end

#class_method_locations(include_super = true, sort: true, only_valid: false) ⇒ Hash<Symbol, NRSER::Meta::Source::Location>

Map class method names to the their source locations.

Parameters:

  • include_super (Boolean) (defaults to: true)

    When ‘true`, includes inherited class methods.

Returns:

See Also:



46
47
48
49
50
51
52
# File 'lib/nrser/core_ext/module/source_locations.rb', line 46

def class_method_locations  include_super = true,
                            sort: true,
                            only_valid: false
  NRSER::Meta::Source::Location.for_methods \
    class_method_objects( include_super, sort: sort ),
    only_valid: only_valid
end

#class_method_objects(include_super = true, sort: true) ⇒ Array<Method> Also known as: class_Methods

Get class methods for this Module (Class are also Module, so works same for those).

Parameters:

  • include_super (Boolean) (defaults to: true)

    When ‘true`, includes inherited class methods.

Returns:

  • (Array<Method>)

    List of method objects (all bound to ‘self`).



17
18
19
20
21
22
# File 'lib/nrser/core_ext/module/method_objects.rb', line 17

def class_method_objects include_super = true, sort: true
  NRSER.method_objects_for  self,
                            include_super,
                            type: :class,
                            sort: sort
end

#demodulize_nameString Also known as: demod_name

Get the #safe_name and run ActiveSupport’s String#demodulize on it to get the module (or class) name without the namespace.

Examples:

NRSER::Types.demod_name
# => 'Types'

Returns:



61
62
63
# File 'lib/nrser/core_ext/module/names.rb', line 61

def demodulize_name
  safe_name.demodulize
end

#instance_method_locations(include_super = true, sort: true, include_initialize: false, only_valid: false) ⇒ Hash<Symbol, NRSER::Meta::Source::Location>

Map instance method names to the their source locations.

Parameters:

  • include_super (Boolean) (defaults to: true)

    When ‘true`, includes inherited class methods.

Returns:

See Also:



79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/nrser/core_ext/module/source_locations.rb', line 79

def instance_method_locations   include_super = true,
                                sort: true,
                                include_initialize: false,
                                only_valid: false
  NRSER::Meta::Source::Location.for_methods \
    instance_method_objects(
      include_super,
      sort: sort,
      include_initialize: include_initialize,
    ),
    only_valid: only_valid
end

#instance_method_objects(include_super = true, sort: true, include_initialize: false) ⇒ Array<UnboundMethod> Also known as: instance_Methods

Get instance methods for this Module (or Class).

Parameters:

  • include_initialize (Boolean) (defaults to: false)

    When ‘true`, include `#initialize` method if it’s defined, which is normally excluded from #instance_methods.

    Respects ‘include_super` - won’t include it if we are only looking for own instance methods and it’s inherited.

  • include_super (Boolean) (defaults to: true)

    When ‘true`, includes inherited class methods.

Returns:



59
60
61
62
63
64
65
66
67
68
# File 'lib/nrser/core_ext/module/method_objects.rb', line 59

def instance_method_objects include_super = true,
                            sort: true,
                            include_initialize: false
  NRSER.method_objects_for \
    self,
    include_super,
    type: :instance,
    sort: sort,
    include_initialize: include_initialize
end

#method_locations(only_valid: false) ⇒ Hash<Method, Array<String, Fixnum>>

Get all source locations for that module (or class) methods - class and instance methods.

Parameters:

  • only_valid (Boolean) (defaults to: false)

    Filter results to only valid source locations.

Returns:



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/nrser/core_ext/module/source_locations.rb', line 119

def method_locations only_valid: false
  # Get all the src locs for own methods
  # own_class_method_locations( only_valid: only_valid ).
  #   map { |name, location|
  #     [".#{ name }", location]
  #   }.
  #   to_h.
  #   merge! \
  #     own_instance_method_locations(  only_valid: only_valid,
  #                                     include_initialize: true ).
  #       map { |name, location|
  #         ["##{ name }", location]
  #       }.to_h
  
  [
    [ '.', own_class_method_locations(    only_valid: only_valid ) ],

    [ '#', own_instance_method_locations( only_valid: only_valid,
                                          include_initialize: true ) ],
    
  ].each_with_object( {} ) do |(prefix, method_locations), result|
    method_locations.each do |name, location|
      result["#{ prefix }#{ name }"] = location
    end
  end
end

#own_class_method_locations(sort: true, only_valid: false) ⇒ Hash<Symbol, NRSER::Meta::Source::Location>

Just calls #class_method_locations with ‘include_super = false`.

Returns:



62
63
64
65
# File 'lib/nrser/core_ext/module/source_locations.rb', line 62

def own_class_method_locations  sort: true,
                                only_valid: false
  class_method_locations false, sort: sort, only_valid: only_valid
end

#own_class_method_objects(sort: true) ⇒ Array<Method> Also known as: own_class_Methods

Just get the class methods defined in this module (or class) itself, omitting inherited ones.

Equivalent to

#class_method_objects false

Returns:

  • (Array<Method>)

    List of method objects (all bound to ‘self`).



37
38
39
# File 'lib/nrser/core_ext/module/method_objects.rb', line 37

def own_class_method_objects sort: true
  class_method_objects false, sort: sort
end

#own_instance_method_locations(sort: true, include_initialize: false, only_valid: false) ⇒ Hash<Symbol, NRSER::Meta::Source::Location>

Just calls #instance_method_locations with ‘include_super = false`.

Returns:



101
102
103
104
105
106
107
108
# File 'lib/nrser/core_ext/module/source_locations.rb', line 101

def own_instance_method_locations sort: true,
                                  include_initialize: false,
                                  only_valid: false
  instance_method_locations false,
                            sort: sort,
                            include_initialize: include_initialize,
                            only_valid: only_valid
end

#own_instance_method_objects(sort: true, include_initialize: false) ⇒ Array<UnboundMethod> Also known as: own_instance_Methods

Just get the instance methods defined in this Module (or Class) itself, omitting inherited ones.

Equivalent to

#instance_method_objects false

Returns:



85
86
87
88
89
90
# File 'lib/nrser/core_ext/module/method_objects.rb', line 85

def own_instance_method_objects sort: true,
                                include_initialize: false
  instance_method_objects false,
                          sort: sort,
                          include_initialize: include_initialize
end

#safe_nameString

Like #name but also returns a String for anonymous classes.

So you don’t need to do any testing or trying when you want to work with the name of a module (or class, which are modules).

Returns:



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/nrser/core_ext/module/names.rb', line 33

def safe_name
  name = self.name
  return name if name.is_a? String
  
  # Slice out whatever that hex thingy that anon modules dump in their
  # `#to_s`... `"#<Class:0x00007fa6958c1700>" => "0x00007fa6958c1700"`
  # 
  # Might as well use that as an identifier so it matches their `#to_s`,
  # and this should still succeed in whatever funky way even if `#to_s`
  # returns something totally unexpected.
  # 
  to_s_hex = self.to_s.split( ':' ).last[0...-1]
  
  type_name = if self.is_a?( Class ) then "Class" else "Module" end
  
  "Anon#{ type_name }_#{ to_s_hex }"
end

#source_locationNRSER::Meta::Source::Location

Try to find a reasonable file and line for the module (or class) by looking at the locations of it’s methods.

Returns:



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/nrser/core_ext/module/source_locations.rb', line 178

def source_location
  # Get all the src locs for all methods
  locations = method_locations only_valid: true
  
  # Short circuit if we don't have shit to work with...
  return NRSER::Meta::Source::Location.new if locations.empty?
  
  # If any files end with the "canonical path" then use that. It's a path
  # suffix
  # 
  #     "my_mod/sub_mod/some_class.rb"
  # 
  # the for a class
  # 
  #     MyMod::SubMod::SomeClass
  # 
  canonical_rel_path = self.canonical_rel_path
  
  unless canonical_rel_path.nil?
    
    # Find first line in canonical path (if any)
    canonical_path_location = locations.
      values.
      find_all { |(path, line)| path.end_with? canonical_rel_path.to_s }.
      min_by { |(path, line)| line }
    
    # If we found one, we're done!
    return canonical_path_location if canonical_path_location
    
  end
  
  # OK, that didn't work, so...
  
  # If it's a {Class} and it has an `#initialize` method, point there.
  # 
  if is_a?( Class ) && locations['#initialize']
    return locations['#initialize']
  end
  
  # No dice. Moving on...
  
  # Get the first line on the shortest path
  locations.values.min_by { |(path, line)|
    [path.length, line]
  }
end