Skip to content

Commit

Permalink
API: added a lookup within multiple namespaces
Browse files Browse the repository at this point in the history
## Usage

```ruby
Scope.namespaces << MyNamespace # => [nil, MyNamespace]
Scope.for MyModel               # => MyNamespace::MyScope
```
  • Loading branch information
Alexander-Senko committed Oct 19, 2024
1 parent cb27824 commit 32d1fa6
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### Added

- Optional `namespace` parameter to `Magic::Lookup#for` for class lookups within a namespace.
- `Magic::Lookup#namespaces` to set default lookup namespaces.


## [0.1.0] — 2024-10-10
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ Scope.for MyModel # => MyScope
Scope.for MyModel, MyNamespace # => MyNamespace::MyScope
```

Multiple default lookup namespaces may be set for the base class:

```ruby
Scope.namespaces << MyNamespace # => [nil, MyNamespace]
Scope.for MyModel # => MyNamespace::MyScope
```

> [!TIP]
> Until a comprehensive documentation on all the use cases is released, the spec is recommended as further reading.
> One can access it by running `rake` in the gem directory.
Expand Down
5 changes: 4 additions & 1 deletion lib/magic/lookup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

module Magic
module Lookup
autoload :Error, 'magic/lookup/error'
autoload :Error, 'magic/lookup/error'
autoload :Namespaces, 'magic/lookup/namespaces'

include Memery

Expand All @@ -25,6 +26,8 @@ module Lookup
.first
end

prepend Namespaces

def name_for(object_class) = raise NotImplementedError

def descendants
Expand Down
21 changes: 21 additions & 0 deletions lib/magic/lookup/namespaces.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

module Magic
module Lookup
module Namespaces
attr_writer :namespaces

def namespaces = @namespaces ||= [ nil ]

def for object_class, *namespaces
return super unless namespaces.empty?

self.namespaces
.reverse # recently added first
.lazy # optimization
.filter_map { super object_class, _1 }
.first
end
end
end
end
26 changes: 26 additions & 0 deletions spec/magic/lookup_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,36 @@ def self.name_for(object_class) = "#{object_class}Scope"
end

describe 'namespaces' do
before { stub_const 'ArrayScope', Class.new(base_class) }
before { stub_const 'Namespace::ArrayScope', Class.new(base_class) }

its([Array, 'Namespace']) { is_expected.to be Namespace::ArrayScope }

context 'when set for the base class' do
before { base_class.namespaces << Namespace }

its([Array ]) { is_expected.to be Namespace::ArrayScope }
its([Array, nil]) { is_expected.to be ArrayScope }

it 'isn’t cached' do
expect(subject[Array]).to be Namespace::ArrayScope
base_class.namespaces.delete Namespace
expect(subject[Array]).to be ArrayScope
end

context 'without matching decorators in the namespace' do
before { base_class.namespaces = [ 'OtherNamespace' ] }

its([Array]) { is_expected.to be_nil }

context 'with a fallback' do
before { base_class.namespaces = [ nil, 'OtherNamespace' ] }

its([Array]) { is_expected.to be ArrayScope }
end
end
end

context 'when target class is namespaced' do
context 'when matching class is of the same namespace' do
before { stub_const 'Enumerator::LazyScope', Class.new(base_class) }
Expand Down

0 comments on commit 32d1fa6

Please sign in to comment.