Skip to content

Commit

Permalink
Merge pull request #10 from danleyden/locations
Browse files Browse the repository at this point in the history
Adding support for inherited mappings
  • Loading branch information
astratto authored Nov 15, 2016
2 parents a502724 + 24fab91 commit 68a5003
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 5 deletions.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,31 @@ DocMyRoutes::Documentation.generate
...
```

Note: there are occasions where an application may be mounted using url map and
be composed of other apps by making use of the 'use' directive in rack. In this
case, you need to tell DocMyRoutes to link the two together. By doing this,
DocMyRoutes will automatically provide documentation for the child apps mounted
wherever the composed app ends up being mounted.

e.g.

```ruby
class MyChildApp; end
class MyOtherChildApp; end

class MyComposedApp
DocMyRoutes::Mapping.inherit_mapping(MyChildApp, self)
DocMyRoutes::Mapping.inherit_mapping(MyOtherChildApp, self)

use MyChildApp
use MyOtherChildApp
end

app = Rack::Builder.app do
run Rack::URLMap.new('/myapp' => MyComposedApp.new)
end
```

## Customisation

Some aspects of DocMyRoutes can be customised to provide a different user
Expand Down
1 change: 1 addition & 0 deletions lib/doc_my_routes/doc/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ module DocMyRoutes
class ExampleMissing < StandardError; end
class UnsupportedError < StandardError; end
class MultipleMappingDetected < UnsupportedError; end
class NoMappingDetected < UnsupportedError; end
end
16 changes: 12 additions & 4 deletions lib/doc_my_routes/doc/mapping.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ def mapping_used?
Object.const_defined?('Rack::URLMap')
end

def inherit_mapping(child_class, super_class)
(@inherited_mappings ||= {})[child_class.to_s] = super_class.to_s
end

# This method associates to each route its namespace, if detected.
#
# Note: when application A is inherited by B and only B is mapped, from
Expand Down Expand Up @@ -100,15 +104,19 @@ def mount_point_for_resource(resource)
class_name = remapped_applications[class_name].first if \
remapped_applications.key?(class_name)

locations = route_mapping[class_name]
validate_locations(class_name, extract_locations(class_name))
end

validate_locations(class_name, locations)
def extract_locations(class_name)
route_mapping[class_name] || route_mapping[(@inherited_mappings || {})[class_name]]
end

# Detects if multiple locations are available and for now fail
def validate_locations(resource, locations)
fail "Resource #{resource} has multiple mappings, but that's not " \
"supported yet: #{locations}" if locations.size > 1
fail NoMappingDetected, "Resource #{resource} has no mapping, so we can't tell where " \
'it is mounted!' if locations.nil?
fail MultipleMappingDetected, "Resource #{resource} has multiple mappings, but that's " \
"not supported yet: #{locations}" if locations.size > 1

return locations.first if locations.size == 1

Expand Down
2 changes: 1 addition & 1 deletion lib/doc_my_routes/version.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# DocMyRoutes version
module DocMyRoutes
VERSION = '0.10.0'
VERSION = '0.11.0'
end
32 changes: 32 additions & 0 deletions spec/system/myapp_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
# The tests are only focused on the route created in each context
# without taking into consideration the real DocMyRoutes routes
DocMyRoutes::RouteCollection.routes.clear
DocMyRoutes::Mapping.instance_variable_set :@remapped_applications, nil
reload_app
end

Expand Down Expand Up @@ -56,5 +57,36 @@
expect(subject.map(&:namespace)).to eq(['/myapp', '/myapp'])
end
end

context 'where a different app is mapped that uses that app' do
let(:other_class) do
Object.send(:remove_const, :MyOtherClass) if Object.constants.include?(:MyOtherClass)
MyOtherClass = Class.new do
def self.class
MyOtherClass
end
end
end

before do
Rack::URLMap.new('/other_app' => other_class)
end

subject { DocMyRoutes::RouteCollection.routes[app_name].map(&:path) }

it 'fails due to no mapping being available' do
expect { subject }.to raise_error DocMyRoutes::NoMappingDetected
end

context 'and the app is marked to inherit the mapping from the different app' do
before do
DocMyRoutes::Mapping.inherit_mapping(Object.const_get(app_name), MyOtherClass)
end

it 'the routes are correctly namespaced' do
expect(subject).to eq(['/other_app', '/other_app'])
end
end
end
end
end

0 comments on commit 68a5003

Please sign in to comment.