register 0.5.3 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/README.md +104 -33
- data/Rakefile +17 -5
- data/lib/register.rb +66 -20
- data/lib/register/version.rb +1 -1
- data/register.gemspec +2 -0
- metadata +30 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9747f4557a3c6de92a37efff1e8a283a8715133a
|
4
|
+
data.tar.gz: 19eba97e52016589e2bc6ca9a7492f042d182940
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b47edbd458b251f7fa1532cfad381d9e8552ed01cf7709883a40003e9831c63e5f785a256bc2b0c9cfdaa3c79ddc790ffffae3f9f594ec2c8d026bc2c9546e5c
|
7
|
+
data.tar.gz: 0f7139bb74ba86e14e6d360c93c30f921b5b76a03dd326fa5246168a992aeeb5fe327f953b62cd57029bc57388f82af2f0b6ef07837e3ff732d1754a498752f4
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--no-private --protected lib/**/*.rb - README.md LICENSE.txt
|
data/README.md
CHANGED
@@ -12,9 +12,11 @@ A good example is a register of several connections to either *Redis* or *MemCac
|
|
12
12
|
|
13
13
|
## Usage
|
14
14
|
|
15
|
+
You need to create a module for each individual "store" — behind the scenes `Register` uses ruby `Hash`, but protects any write access to it using a local mutex to ensure thread-safety.
|
16
|
+
|
15
17
|
### Creating a Register
|
16
18
|
|
17
|
-
To create a register module, just include `Register` in any ruby
|
19
|
+
To create a register module, just include `Register` in any of your custom ruby modules:
|
18
20
|
|
19
21
|
```ruby
|
20
22
|
require 'register'
|
@@ -24,9 +26,13 @@ module Cache
|
|
24
26
|
end
|
25
27
|
```
|
26
28
|
|
27
|
-
###
|
29
|
+
### Adding Items to the Register
|
30
|
+
|
31
|
+
To add items to the register, call the `#register` method on the module (or it's alias `.<<`, passing an array of identifiers first, followed by the actual item to store.
|
28
32
|
|
29
|
-
|
33
|
+
In other words, the very last item of the argument array is the actual item stored against each of the keys passed in an array before it.
|
34
|
+
|
35
|
+
The `#register` method returns the item successfully stored, or raises one of several exceptions.
|
30
36
|
|
31
37
|
```ruby
|
32
38
|
|
@@ -34,66 +40,131 @@ To add items to the register, call the `<<` method, passing an array of identifi
|
|
34
40
|
CacheStore = Struct.new(:name)
|
35
41
|
|
36
42
|
# Register items associated with any one of the identifiers
|
37
|
-
Cache.register :planetary,
|
43
|
+
Cache.register :planetary,
|
44
|
+
:cosmic,
|
45
|
+
CacheStore.new(:saturn)
|
46
|
+
#=> #<struct CacheStore name=:saturn>
|
47
|
+
|
48
|
+
# Use the block syntax to define the value:
|
49
|
+
Cache.register(*%i[primary main rails deploy]) do
|
50
|
+
CacheStore.new(:primary)
|
51
|
+
end
|
52
|
+
#=> #<struct CacheStore name=:primary>
|
38
53
|
|
39
|
-
#
|
40
|
-
#
|
41
|
-
Cache
|
54
|
+
# Use the << method alias instead (just ensure the proper
|
55
|
+
# grouping of the arguments)
|
56
|
+
Cache << %i[number].push(Math::PI)
|
57
|
+
#=> 3.141592653589793
|
42
58
|
|
43
|
-
|
59
|
+
# Using double << with ()
|
60
|
+
Cache << (%i[durable secondary] << CacheStore.new(:secondary))
|
61
|
+
#=> #<struct CacheStore name=:secondary>
|
44
62
|
```
|
45
63
|
|
46
|
-
|
64
|
+
#### Exceptions while Adding Items
|
65
|
+
|
66
|
+
* `AlreadyRegisteredError` is thrown when the key is already in the store, and the option `:ignore_if_exists` is not passed to the `register()` method;
|
67
|
+
|
68
|
+
* `ReservedIdentifierError` is thrown upon an attempt to register a keyword that is reserved (i.e. clashes with one of the methods on the blank `Module`).
|
69
|
+
|
70
|
+
|
71
|
+
### Fetching an Item from the Register
|
47
72
|
|
48
73
|
There are two ways to fetch the previously-stored item:
|
49
74
|
|
50
75
|
1. Using the `#for(:name)` method
|
76
|
+
|
51
77
|
2. Using the auto-generated module-level accessor
|
52
78
|
|
53
79
|
In the first example, we would call `Cache.for(:planetary)` to fetch the cache store, while in the second case we would call `Cache.planetary` method, which provides additional guarantees: if the method is not there, something is definitely wrong.
|
54
80
|
|
55
81
|
```ruby
|
56
|
-
Cache.
|
57
|
-
|
82
|
+
Cache.cosmic
|
83
|
+
# => #<struct CacheStore name=:saturn>
|
84
|
+
Cache.planetary.name
|
85
|
+
# => :saturn
|
86
|
+
Cache.primary == Cache.main == Cache.rails == Cache.deploy
|
87
|
+
# => true
|
58
88
|
Cache.durable.name = 'DURABLE'
|
59
|
-
|
89
|
+
# => 'DURABLE'
|
90
|
+
Cache.secondary.name
|
91
|
+
# => 'DURABLE'
|
60
92
|
```
|
61
93
|
|
62
|
-
|
94
|
+
#### Exceptions while Fetching Items
|
95
|
+
|
96
|
+
* `NoSuchIdentifierError` is thrown upon lookup with method `#for` when no requested key was found in the store;
|
97
|
+
|
98
|
+
## Contributing
|
99
|
+
|
100
|
+
* Fork the project.
|
101
|
+
* Make your feature addition or bug fix.
|
102
|
+
* Add specs for it, as without tests the PR will be rejected.
|
103
|
+
* Do not change the version.
|
104
|
+
* Send a pull request, with a well worded description.
|
105
|
+
|
106
|
+
|
107
|
+
There are some additional methods that will help you debug should things go weird:
|
108
|
+
|
109
|
+
### Additional Methods: `#keys` and `#values`
|
110
|
+
|
111
|
+
These two methods proxy into the underlying `Hash`. The `#values` method returns the uniq'd array of the values.
|
63
112
|
|
64
113
|
```ruby
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
114
|
+
# ap Cache.keys
|
115
|
+
[
|
116
|
+
[0] :planetary,
|
117
|
+
[1] :cosmic,
|
118
|
+
[2] :primary,
|
119
|
+
[3] :main,
|
120
|
+
[4] :rails,
|
121
|
+
[5] :deploy,
|
122
|
+
[6] :durable,
|
123
|
+
[7] :secondary,
|
124
|
+
[8] :number
|
125
|
+
]
|
126
|
+
# ap Cache.store.values.uniq
|
127
|
+
[
|
128
|
+
[0] #<Struct:CacheStore:0x7facd107c800
|
129
|
+
name = :saturn
|
130
|
+
>,
|
131
|
+
[1] #<Struct:CacheStore:0x7facd2836c98
|
132
|
+
name = :primary
|
133
|
+
>,
|
134
|
+
[2] #<Struct:CacheStore:0x7facd281fa98
|
135
|
+
name = :secondary
|
136
|
+
>,
|
137
|
+
[3] 3.141592653589793
|
138
|
+
]
|
76
139
|
```
|
77
|
-
|
140
|
+
|
141
|
+
### Internal Storage
|
142
|
+
|
143
|
+
This gem uses a plain ruby `Hash` to store the values, but protects write access with a `Mutex`.
|
144
|
+
|
145
|
+
While it is not advisable to manipulate the underlying storage, you can access it via `Cache.send(:store)`, i.e:
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
Cache.send(:store).class
|
149
|
+
# => Hash
|
150
|
+
```
|
151
|
+
|
78
152
|
## Installation
|
79
153
|
|
80
154
|
gem install register
|
155
|
+
|
156
|
+
Or if you are using Bundler, add the following to your `Gemfile`:
|
81
157
|
|
82
|
-
|
83
|
-
|
84
|
-
* Fork the project.
|
85
|
-
* Make your feature addition or bug fix.
|
86
|
-
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
87
|
-
* Commit, do not mess with rakefile, version, or history. If you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull.
|
88
|
-
* Send a pull request. Bonus points for topic branches.
|
158
|
+
gem 'register'
|
89
159
|
|
90
160
|
## Copyright
|
91
161
|
|
92
|
-
Copyright © 2017 Konstantin Gredeskoul. See LICENSE for details.
|
162
|
+
Copyright © 2017 Konstantin Gredeskoul. See [LICENSE](LICENSE.txt) for details.
|
93
163
|
|
94
164
|
## Contributors
|
95
165
|
|
96
166
|
* [Konstantin Gredeskoul](https://github.com/kigster)
|
167
|
+
* You?
|
97
168
|
|
98
169
|
|
99
170
|
|
data/Rakefile
CHANGED
@@ -1,23 +1,35 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
2
|
require 'rspec/core/rake_task'
|
3
3
|
require 'yard'
|
4
|
+
require 'colored2'
|
4
5
|
|
5
6
|
def shell(*args)
|
6
|
-
puts "running: #{args.join(' ')}"
|
7
|
+
puts "running: #{args.join(' ').blue.bold}".yellow
|
7
8
|
system(args.join(' '))
|
8
9
|
end
|
9
10
|
|
11
|
+
module Register
|
12
|
+
DIST_DIRS=%w(lib)
|
13
|
+
BIN_DIRS=%w()
|
14
|
+
end
|
15
|
+
|
10
16
|
task :permissions do
|
11
17
|
shell('rm -rf pkg/')
|
12
|
-
|
13
|
-
|
14
|
-
|
18
|
+
Register::BIN_DIRS.each do |dir|
|
19
|
+
shell("chmod -v o+rx,g+rx #{dir}/*")
|
20
|
+
end
|
21
|
+
|
22
|
+
Register::DIST_DIRS.each do |dir|
|
23
|
+
shell("chmod -v o+rx,g+rx #{dir}")
|
24
|
+
shell("find #{dir} -name '[a-z]*' -type d -exec chmod o+rx,g+rx {} \\; -print")
|
25
|
+
shell("find #{dir} -type f -exec chmod o+r,g+r {} \\; -print")
|
26
|
+
end
|
15
27
|
end
|
16
28
|
|
17
29
|
task :build => :permissions
|
18
30
|
|
19
31
|
YARD::Rake::YardocTask.new(:doc) do |t|
|
20
|
-
t.files = %w(lib/**/*.rb exe/*.rb
|
32
|
+
t.files = %w(lib/**/*.rb exe/*.rb - README.md LICENSE.txt )
|
21
33
|
t.options.unshift('--title','Register - An easy way to create Mudule-level accessors to global resources')
|
22
34
|
t.after = ->() { exec('open doc/index.html') }
|
23
35
|
end
|
data/lib/register.rb
CHANGED
@@ -1,31 +1,73 @@
|
|
1
1
|
require 'register/version'
|
2
2
|
require 'colored2'
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
# **Register** is a tiny library that can be included in a module
|
6
|
+
# that is to become a Façade to several application globals via
|
7
|
+
# auto-generated module-level methods.
|
8
|
+
#
|
9
|
+
# A good example is a register of several connections to either
|
10
|
+
# *Redis* or *MemCached*, for example you might have a short-term
|
11
|
+
# memcached connection with a short default expiration TTL, and a
|
12
|
+
# longer-living one that requires sweeping to clean. You could
|
13
|
+
# use `Register` to wrap access to these singletons in
|
14
|
+
# `MyModule.cache_type` accessors.
|
15
|
+
#
|
16
|
+
# Usage
|
17
|
+
# =====
|
18
|
+
#
|
19
|
+
# To create a register module, just include `Register` in any
|
20
|
+
# of your custom ruby modules:
|
21
|
+
#
|
22
|
+
# require 'register'
|
23
|
+
#
|
24
|
+
# module Cache
|
25
|
+
# include Register
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# Cache.register :rails, Rails.cache
|
29
|
+
# Cache.register :durable, ActiveSupport::Cache::DalliStore.new(
|
30
|
+
# ENV['MEMCACHED_HOSTS'] ? ENV['MEMCACHED_HOSTS'].split(',') : %w[localhost:11211],
|
31
|
+
# namespace: 'v1',
|
32
|
+
# socket_timeout: 0.2,
|
33
|
+
# expires_in: 0, # never expire
|
34
|
+
# keepalive: true,
|
35
|
+
# compress: true,
|
36
|
+
# failover: true
|
37
|
+
# )
|
38
|
+
#
|
39
|
+
# Cache.rails # => Rails.cache
|
40
|
+
# Cache.durable # => DalliStore, etc.
|
41
|
+
#
|
3
42
|
module Register
|
4
43
|
class RegisterError < StandardError; end
|
5
44
|
class AlreadyRegisteredError < RegisterError; end
|
6
45
|
class NoSuchIdentifierError < RegisterError; end
|
7
46
|
class ReservedIdentifierError < RegisterError; end
|
8
47
|
|
9
|
-
|
10
|
-
end
|
11
|
-
|
12
|
-
RESERVED = (DummyModule.methods << %i[for register << add_method]).flatten!.freeze
|
48
|
+
RESERVED = (Register.methods + %i[for register keys values << add_method]).flatten.uniq.freeze
|
13
49
|
|
14
50
|
def self.included(klass)
|
15
51
|
klass.instance_eval do
|
16
52
|
@store = Hash.new
|
17
53
|
@mutex = Mutex.new
|
18
54
|
class << self
|
19
|
-
|
20
|
-
|
55
|
+
extend Forwardable
|
56
|
+
def_delegators :@store, :keys
|
57
|
+
attr_accessor :mutex
|
58
|
+
|
59
|
+
def << *names, **opts, &block
|
21
60
|
names.flatten!
|
22
61
|
item = block ? yield(self) : names.pop
|
23
|
-
validate_existing_keys!(names)
|
24
62
|
validate_reserved_keys!(names)
|
25
|
-
|
26
|
-
|
27
|
-
|
63
|
+
@mutex.synchronize do
|
64
|
+
validate_existing_keys!(names, opts)
|
65
|
+
names.each do |n|
|
66
|
+
store[n] = item
|
67
|
+
add_method(n)
|
68
|
+
end
|
28
69
|
end
|
70
|
+
item
|
29
71
|
end
|
30
72
|
|
31
73
|
alias register <<
|
@@ -38,19 +80,25 @@ module Register
|
|
38
80
|
store[id]
|
39
81
|
end
|
40
82
|
|
83
|
+
def values
|
84
|
+
store.values.uniq
|
85
|
+
end
|
86
|
+
|
41
87
|
private
|
42
88
|
|
89
|
+
def store
|
90
|
+
@store
|
91
|
+
end
|
92
|
+
|
43
93
|
def add_method(id)
|
44
94
|
return unless id.is_a?(Symbol)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
method_defs = %Q!
|
95
|
+
unless self.respond_to?(id)
|
96
|
+
line_no = __LINE__
|
97
|
+
method_defs = %Q!
|
49
98
|
def self.#{id}
|
50
99
|
store[:#{id}]
|
51
100
|
end\n!
|
52
|
-
|
53
|
-
end
|
101
|
+
module_eval method_defs, __FILE__, line_no
|
54
102
|
end
|
55
103
|
end
|
56
104
|
|
@@ -61,14 +109,12 @@ module Register
|
|
61
109
|
end
|
62
110
|
end
|
63
111
|
|
64
|
-
def validate_existing_keys!(names)
|
112
|
+
def validate_existing_keys!(names, opts = {})
|
65
113
|
already = names.select { |n| store.key?(n) }
|
66
|
-
|
114
|
+
if !already.empty? && opts[:ignore_if_exists].nil?
|
67
115
|
raise AlreadyRegisteredError, "The following keys are already in the registry: #{already}"
|
68
116
|
end
|
69
117
|
end
|
70
|
-
|
71
|
-
|
72
118
|
end
|
73
119
|
end
|
74
120
|
end
|
data/lib/register/version.rb
CHANGED
data/register.gemspec
CHANGED
@@ -21,7 +21,9 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_development_dependency 'simplecov'
|
22
22
|
spec.add_development_dependency 'codeclimate-test-reporter'
|
23
23
|
spec.add_development_dependency 'colored2'
|
24
|
+
spec.add_development_dependency 'irbtools'
|
24
25
|
spec.add_development_dependency 'yard'
|
26
|
+
spec.add_development_dependency 'yard-rspec'
|
25
27
|
spec.add_development_dependency 'awesome_print'
|
26
28
|
spec.add_development_dependency 'bundler', '~> 1.15'
|
27
29
|
spec.add_development_dependency 'rake', '~> 10.0'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: register
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Konstantin Gredeskoul
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: irbtools
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: yard
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +80,20 @@ dependencies:
|
|
66
80
|
- - ">="
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: yard-rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
69
97
|
- !ruby/object:Gem::Dependency
|
70
98
|
name: awesome_print
|
71
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -152,6 +180,7 @@ files:
|
|
152
180
|
- ".rspec"
|
153
181
|
- ".rubocop.yml"
|
154
182
|
- ".travis.yml"
|
183
|
+
- ".yardopts"
|
155
184
|
- Gemfile
|
156
185
|
- LICENSE.txt
|
157
186
|
- README.md
|