Skip to content

Commit 27872aa

Browse files
aridlehooverFito
andcommitted
Adds class registry and factory
- Abstract classes can extend Replicator::Replicable to make their descendants "replicable" - Concrete, "replicable" classes can self register under one or more keys by calling `replicates :symbol` - Multiple concrete, "replicable" classes can self register under the same key by calling `replicates :symbol` - Registered, "replicable" classes can be instantiated using the abstract parent's `.replicate(:symbol)` method Co-authored-by: Fito von Zastrow <adolfovon@gmail.com>
1 parent 10e292f commit 27872aa

File tree

5 files changed

+98
-17
lines changed

5 files changed

+98
-17
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12-
- Adds interface for building objects with Replicator
12+
- Abstract classes can extend Replicator::Replicable to make their descendants "replicable"
13+
- Concrete, "replicable" classes can self register under one or more keys by calling `replicates :symbol`
14+
- Multiple concrete, "replicable" classes can self register under the same key by calling `replicates :symbol`
15+
- Registered, "replicable" classes can be instantiated using the abstract parent's `.replicate(:symbol)` method

README.md

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# replicator
1+
# Replicator
22

3-
TODO: Write a description here
3+
Replicator is a class registry and factory.
44

55
## Installation
66

@@ -9,7 +9,7 @@ TODO: Write a description here
99
```yaml
1010
dependencies:
1111
replicator:
12-
github: your-github-user/replicator
12+
github: first-try-software/replicator
1313
```
1414
1515
2. Run `shards install`
@@ -18,22 +18,43 @@ TODO: Write a description here
1818

1919
```crystal
2020
require "replicator"
21+
22+
abstract class Starship
23+
extend Replicator::Replicable
24+
end
25+
26+
class Enterprise < Starship
27+
replicates :galaxy
28+
end
29+
30+
class Cerritos < Starship
31+
replicates :galaxy
32+
end
33+
34+
Starship.replicate(:galaxy) # => [#<Enterprise:0x1099ddd60>, #<Cerritos:0x1099ddd70>] : Array(Starship)
2135
```
2236

23-
TODO: Write usage instructions here
37+
## Roadmap
2438

25-
## Development
39+
Replicator is ready to use in it's current state. The interfaces are unlikey to change. But, there will be new features added per our roadmap:
2640

27-
TODO: Write development instructions here
41+
- [x] Abstract classes can extend Replicator::Replicable to make their descendants "replicable"
42+
- [x] Concrete, "replicable" classes can self register under one or more keys by calling `replicates :symbol`
43+
- [x] Multiple concrete, "replicable" classes can self register under the same key by calling `replicates :symbol`
44+
- [x] Registered, "replicable" classes can be instantiated using the abstract parent's `.replicate(:symbol)` method
45+
- [ ] Positional and named arguments may be passed when initializing "replicable" classes
46+
- [ ] A "replicable" class may register as the `default_replica` for an extended abstract parent class, and will be instantiated when an unknown key is requested (good for the null object pattern)
47+
- [ ] A "replicable" class may register as `replicates_all` in which case, it is always instantiated and returned in addition to the classes that match a requested key
2848

2949
## Contributing
3050

31-
1. Fork it (<https://github.com/your-github-user/replicator/fork>)
51+
1. Fork it (<https://github.com/first-try-software/replicator/fork>)
3252
2. Create your feature branch (`git checkout -b my-new-feature`)
3353
3. Commit your changes (`git commit -am 'Add some feature'`)
3454
4. Push to the branch (`git push origin my-new-feature`)
3555
5. Create a new Pull Request
3656

3757
## Contributors
3858

39-
- [Alan Ridlehoover](https://github.com/your-github-user) - creator and maintainer
59+
- [Alan Ridlehoover](https://github.com/aridlehoover) - co-creator and maintainer
60+
- [Fito von Zastrow](https://github.com/Fito) - co-creator and maintainer

spec/replicator_spec.cr

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
11
require "./spec_helper"
22

3-
class Galaxy; extend Replicator::Replicable; end
3+
abstract class Starship; extend Replicator::Replicable; end
4+
class Enterprise < Starship; replicates :galaxy; replicates :enterprise; end
5+
class Cerritos < Starship; replicates :galaxy; replicates :cerritos; end
46

57
Spectator.describe Replicator do
6-
describe ".build" do
7-
it "returns an empty array when an unregistered class is provided" do
8-
replicas = Galaxy.build(:iks_buruk)
9-
expect(replicas.size).to eq(0)
10-
end
8+
it "returns an empty array when an unregistered class is requested" do
9+
replicas = Starship.replicate(:iks_buruk)
10+
expect(replicas.size).to eq(0)
11+
end
12+
13+
it "allows a class to be registered under multiple keys" do
14+
replicas = Starship.replicate(:enterprise)
15+
expect(replicas.size).to eq(1)
16+
expect(replicas.first).to be_a_kind_of(Enterprise)
17+
end
18+
19+
it "allows multiple classes to be registred under the same key" do
20+
replicas = Starship.replicate(:galaxy)
21+
expect(replicas.size).to eq(2)
22+
expect(replicas.first).to be_a_kind_of(Enterprise)
23+
expect(replicas.last).to be_a_kind_of(Cerritos)
1124
end
1225
end

src/replicator/registry.cr

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
module Replicator
2+
class Registry(K, V)
3+
private getter :registry
4+
5+
def initialize
6+
@registry = Hash(K, Set(V)).new
7+
end
8+
9+
def add(key : K, value)
10+
setup_registry_for(key)
11+
items_for(key).add(value)
12+
end
13+
14+
def get(key : K)
15+
items_for(key)
16+
end
17+
18+
private def setup_registry_for(key)
19+
registry[key] ||= Set(V).new
20+
end
21+
22+
private def items_for(key)
23+
registered?(key) ? registry[key] : Set(V).new
24+
end
25+
26+
private def registered?(key : K)
27+
registry.keys.includes?(key)
28+
end
29+
end
30+
end

src/replicator/replicable.cr

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
1+
require "./registry"
2+
13
module Replicator
24
module Replicable
3-
def build(key)
4-
Array(String).new
5+
macro extended
6+
def self.replicates(key)
7+
{{@type}}.__replicable_registry.add(key, self)
8+
end
9+
10+
def self.replicate(key)
11+
{{@type}}.__replicable_registry
12+
.get(key)
13+
.map { |klass| klass.new }
14+
end
15+
16+
protected def self.__replicable_registry
17+
@@__replicable_registry ||= Replicator::Registry(Symbol, {{@type.class}}).new
18+
end
519
end
620
end
721
end

0 commit comments

Comments
 (0)