Class: DocMyRoutes::Mapping

Inherits:
Object
  • Object
show all
Defined in:
lib/doc_my_routes/doc/mapping.rb

Overview

Class that maintain information about the route mapping, as extracted from the actual application

Sinatra applications define routes and can be mapped on different namespaces as happens with normal Rack applications.

That means that given an application A that provides:

- GET /my_route

its actual route might become /my_application/my_route using for instance:

Rack::Builder.app do

run Rack::URLMap.new ('my_application' => A)

end

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.route_mappingObject (readonly)

Returns the value of attribute route_mapping.



20
21
22
# File 'lib/doc_my_routes/doc/mapping.rb', line 20

def route_mapping
  @route_mapping
end

Class Method Details

.assign_namespaceObject

This method associates to each route its namespace, if detected.

Note: when application A is inherited by B and only B is mapped, from the point of view of the mapping only B is defined.

Technically speaking, this is absolutely correct because B is the actual application that’s registered and used (B provides A’s methods).

This method duplicates routes for applications that are not mapped in order to list their routes among the ones of the resources that inherit from them



50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/doc_my_routes/doc/mapping.rb', line 50

def assign_namespace
  RouteCollection.routes.each do |class_name, app_routes|
    # TODO: deal with multiple locations for multi mapping
    if route_mapping.include?(class_name)
      app_routes.each do |route|
        route.namespace = @route_mapping[class_name].first
      end
    else
      remap_resource(class_name)
    end
  end
end

.extract_mapping(mapping) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/doc_my_routes/doc/mapping.rb', line 22

def extract_mapping(mapping)
  @route_mapping = {}
  mapping.each do |_, location, _, app|
    klass = app.class
    klass = app.instance_variable_get('@instance').class \
      if klass == Sinatra::Wrapper

    (@route_mapping[klass.to_s] ||= []) << location
  end

  assign_namespace
end

.find_child_apps(class_name) ⇒ Object

Returns the mapped application(s) that inherited from a given class



84
85
86
87
88
89
# File 'lib/doc_my_routes/doc/mapping.rb', line 84

def find_child_apps(class_name)
  klass = Object.const_get(class_name)
  route_mapping.select do |mapped_app, _|
    Object.const_get(mapped_app).ancestors.include?(klass)
  end
end

.mapping_used?Boolean

Returns:

  • (Boolean)


35
36
37
# File 'lib/doc_my_routes/doc/mapping.rb', line 35

def mapping_used?
  Object.const_defined?('Rack::URLMap')
end

.mount_point_for_resource(resource) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/doc_my_routes/doc/mapping.rb', line 91

def mount_point_for_resource(resource)
  class_name = resource.to_s
  unless route_mapping
    DocMyRoutes.logger.debug 'URLMap not used for resource ' \
                             "#{class_name}, assuming it's not namespaced"
    return '/'
  end

  # TODO: support multiple application inheriting
  class_name = remapped_applications[class_name].first if \
    remapped_applications.key?(class_name)

  locations = route_mapping[class_name]

  validate_locations(class_name, locations)
end

.remap_resource(class_name) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/doc_my_routes/doc/mapping.rb', line 67

def remap_resource(class_name)
  DocMyRoutes.logger.debug 'Remapping routes for not mapped ' \
                           "resource #{class_name}"

  find_child_apps(class_name).each do |child, location|
    DocMyRoutes.logger.debug " - Remapping to #{child}"
    remapped_applications[class_name] << child

    RouteCollection.routes[class_name].each do |route|
      # TODO: If an application has multiple namespaces, we should
      # keep a list of aliases
      route.namespace = location.first
    end
  end
end

.remapped_applicationsObject



63
64
65
# File 'lib/doc_my_routes/doc/mapping.rb', line 63

def remapped_applications
  @remapped_applications ||= Hash.new { |hash, key| hash[key] = [] }
end

.validate_locations(resource, locations) ⇒ Object

Detects if multiple locations are available and for now fail



109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/doc_my_routes/doc/mapping.rb', line 109

def validate_locations(resource, locations)
  fail "Resource #{resource} has multiple mappings, but that's not " \
        "supported yet: #{locations}" if locations.size > 1

  return locations.first if locations.size == 1

  DocMyRoutes.logger.debug 'Unable to extract mapping for resource ' \
                           "#{resource}, it's not mapped! This is not " \
                           'necessarily a bug and might happen ' \
                           "because #{resource} is inherited and its " \
                           'children are mapped.'
  nil
end