dry-core 0.1.0
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 +7 -0
- data/.gitignore +10 -0
- data/.inch.yml +4 -0
- data/.rspec +3 -0
- data/.rubocop.yml +31 -0
- data/.travis.yml +28 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +21 -0
- data/README.md +47 -0
- data/Rakefile +6 -0
- data/dry-core.gemspec +33 -0
- data/lib/dry-core.rb +1 -0
- data/lib/dry/core.rb +8 -0
- data/lib/dry/core/cache.rb +66 -0
- data/lib/dry/core/class_builder.rb +38 -0
- data/lib/dry/core/constants.rb +49 -0
- data/lib/dry/core/deprecations.rb +157 -0
- data/lib/dry/core/extensions.rb +53 -0
- data/lib/dry/core/version.rb +5 -0
- metadata +119 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f18461caed54954ed1ded7991e22481fb2460f54
|
4
|
+
data.tar.gz: 6f14a3398ad397e64db754967b4315a440b225f1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b68b62a1b7bceb698b669c9462c4bfded77dd1536dbcaaa201c76c34414df3d28e85042e106d2809ad118caabbd8ce84a4e5d09da835cf03dfa7f1f53ea7cda7
|
7
|
+
data.tar.gz: 0960b20d7483027f61502c64c0c06d69f37bca79c90f6bc4aedc190328bf9d354ca323c17e34a28a281f9cf27b59b6acd6c51fb0d7f36089fb1665d9103257e2
|
data/.gitignore
ADDED
data/.inch.yml
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.1
|
3
|
+
Exclude:
|
4
|
+
- 'dry-core.gemspec'
|
5
|
+
- 'spec/spec_helper.rb'
|
6
|
+
|
7
|
+
Style/SignalException:
|
8
|
+
Exclude:
|
9
|
+
- 'spec/**/*'
|
10
|
+
|
11
|
+
Style/RedundantSelf:
|
12
|
+
Exclude:
|
13
|
+
- 'lib/dry/core/deprecations.rb'
|
14
|
+
|
15
|
+
Metrics/LineLength:
|
16
|
+
Max: 110
|
17
|
+
|
18
|
+
Metrics/MethodLength:
|
19
|
+
Enabled: false
|
20
|
+
|
21
|
+
Style/FileName:
|
22
|
+
Exclude:
|
23
|
+
- 'lib/dry-core.rb'
|
24
|
+
|
25
|
+
Lint/AmbiguousRegexpLiteral:
|
26
|
+
Exclude:
|
27
|
+
- 'spec/**/*'
|
28
|
+
|
29
|
+
Style/BlockDelimiters:
|
30
|
+
Exclude:
|
31
|
+
- 'spec/**/*'
|
data/.travis.yml
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
sudo: false
|
2
|
+
language: ruby
|
3
|
+
rvm:
|
4
|
+
- 2.1.9
|
5
|
+
- 2.2.5
|
6
|
+
- 2.3.1
|
7
|
+
- rbx-2
|
8
|
+
- jruby-9.1.4.0
|
9
|
+
- ruby-head
|
10
|
+
|
11
|
+
before_install: gem update bundler
|
12
|
+
matrix:
|
13
|
+
allow_failures:
|
14
|
+
- rvm: ruby-head
|
15
|
+
notifications:
|
16
|
+
email:
|
17
|
+
recipients:
|
18
|
+
- fg@flashgordon.ru
|
19
|
+
on_success: change
|
20
|
+
on_failure: always
|
21
|
+
on_start: false # default: false
|
22
|
+
webhooks:
|
23
|
+
urls:
|
24
|
+
- https://webhooks.gitter.im/e/19098b4253a72c9796db
|
25
|
+
on_success: change # options: [always|never|change] default: always
|
26
|
+
on_failure: always # options: [always|never|change] default: always
|
27
|
+
on_start: false # default: false
|
28
|
+
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Nikita Shilnikov
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
[gitter]: https://gitter.im/dry-rb/chat
|
2
|
+
[gem]: https://rubygems.org/gems/dry-core
|
3
|
+
[travis]: https://travis-ci.org/dry-rb/dry-core
|
4
|
+
[code_climate]: https://codeclimate.com/github/dry-rb/dry-core
|
5
|
+
[inch]: http://inch-ci.org/github/dry-rb/dry-core
|
6
|
+
|
7
|
+
# dry-core
|
8
|
+
|
9
|
+
[][gem]
|
10
|
+
[][travis]
|
11
|
+
[][code_climate]
|
12
|
+
[][code_climate]
|
13
|
+
[][inch]
|
14
|
+

|
15
|
+
|
16
|
+
A collection of small modules used in the dry-rb ecosystem.
|
17
|
+
|
18
|
+
## Installation
|
19
|
+
|
20
|
+
Add this line to your application's Gemfile:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
gem 'dry-core'
|
24
|
+
```
|
25
|
+
|
26
|
+
And then execute:
|
27
|
+
|
28
|
+
$ bundle
|
29
|
+
|
30
|
+
Or install it yourself as:
|
31
|
+
|
32
|
+
$ gem install dry-core
|
33
|
+
|
34
|
+
## Development
|
35
|
+
|
36
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
37
|
+
|
38
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
39
|
+
|
40
|
+
## Contributing
|
41
|
+
|
42
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/dry-rb/dry-core.
|
43
|
+
|
44
|
+
|
45
|
+
## License
|
46
|
+
|
47
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/dry-core.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'dry/core/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'dry-core'
|
7
|
+
spec.version = Dry::Core::VERSION
|
8
|
+
spec.authors = ['Nikita Shilnikov']
|
9
|
+
spec.email = ['fg@flashgordon.ru']
|
10
|
+
|
11
|
+
spec.summary = 'A toolset of small support modules used throughout the dry-rb ecosystem.'
|
12
|
+
spec.description = spec.summary
|
13
|
+
spec.homepage = 'https://github.com/dry-rb/dry-code'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
if spec.respond_to?(:metadata)
|
19
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
20
|
+
else
|
21
|
+
raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
|
22
|
+
end
|
23
|
+
|
24
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|bin)/}) }
|
25
|
+
spec.bindir = 'exe'
|
26
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
+
spec.require_paths = ['lib']
|
28
|
+
spec.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
|
29
|
+
|
30
|
+
spec.add_development_dependency 'bundler', '~> 1.12'
|
31
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
32
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
33
|
+
end
|
data/lib/dry-core.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'dry-core'
|
data/lib/dry/core.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'concurrent/map'
|
2
|
+
|
3
|
+
module Dry
|
4
|
+
module Core
|
5
|
+
# Allows you to cache call results that are solely determined by arguments.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# require 'dry/core/cache'
|
9
|
+
#
|
10
|
+
# class Foo
|
11
|
+
# extend Dry::Core::Cache
|
12
|
+
#
|
13
|
+
# def heavy_computation(arg1, arg2)
|
14
|
+
# fetch_or_store(arg1, arg2) { arg1 ^ arg2 }
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# @api public
|
19
|
+
module Cache
|
20
|
+
# @api private
|
21
|
+
def self.extended(klass)
|
22
|
+
super
|
23
|
+
klass.include(Methods)
|
24
|
+
klass.instance_variable_set(:@__cache__, Concurrent::Map.new)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @api private
|
28
|
+
def inherited(klass)
|
29
|
+
super
|
30
|
+
klass.instance_variable_set(:@__cache__, cache)
|
31
|
+
end
|
32
|
+
|
33
|
+
# @api private
|
34
|
+
def cache
|
35
|
+
@__cache__
|
36
|
+
end
|
37
|
+
|
38
|
+
# Caches a result of the block evaluation
|
39
|
+
#
|
40
|
+
# @param [Array<Object>] args List of hashable objects
|
41
|
+
# @yield An arbitrary block
|
42
|
+
#
|
43
|
+
# @note beware Proc instance hashes are not equal, i.e. -> { 1 }.hash != -> { 1 }.hash,
|
44
|
+
# this means you shouldn't pass Procs in args unless you're sure
|
45
|
+
# they are always the same instances, otherwise you introduce a memory leak
|
46
|
+
#
|
47
|
+
# @return [Object] block's return value (cached for subsequent calls with the same argument values)
|
48
|
+
def fetch_or_store(*args, &block)
|
49
|
+
cache.fetch_or_store(args.hash, &block)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Instance methods
|
53
|
+
module Methods
|
54
|
+
# Delegates call to the class-level method
|
55
|
+
#
|
56
|
+
# @param [Array<Object>] args List of hashable objects
|
57
|
+
# @yield An arbitrary block
|
58
|
+
#
|
59
|
+
# @return [Object] block's return value
|
60
|
+
def fetch_or_store(*args, &block)
|
61
|
+
self.class.fetch_or_store(*args, &block)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Dry
|
2
|
+
module Core
|
3
|
+
# Class for generating more classes
|
4
|
+
class ClassBuilder
|
5
|
+
attr_reader :name
|
6
|
+
attr_reader :parent
|
7
|
+
|
8
|
+
def initialize(name:, parent: Object)
|
9
|
+
@name = name
|
10
|
+
@parent = parent
|
11
|
+
end
|
12
|
+
|
13
|
+
# Generate a class based on options
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# builder = Dry::Core::ClassBuilder.new(name: 'MyClass')
|
17
|
+
#
|
18
|
+
# klass = builder.call
|
19
|
+
# klass.name # => "MyClass"
|
20
|
+
#
|
21
|
+
# @return [Class]
|
22
|
+
def call
|
23
|
+
klass = Class.new(parent)
|
24
|
+
name = self.name
|
25
|
+
|
26
|
+
klass.singleton_class.class_eval do
|
27
|
+
define_method(:name) { name }
|
28
|
+
alias_method :inspect, :name
|
29
|
+
alias_method :to_s, :name
|
30
|
+
end
|
31
|
+
|
32
|
+
yield(klass) if block_given?
|
33
|
+
|
34
|
+
klass
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Dry
|
4
|
+
module Core
|
5
|
+
# A list of constants you can use to avoid memory allocations or identity checks.
|
6
|
+
#
|
7
|
+
# @example Just include this module to your class or module
|
8
|
+
# class Foo
|
9
|
+
# def call(value = EMPTY_ARRAY)
|
10
|
+
# value.map(&:to_s)
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# @api public
|
15
|
+
module Constants
|
16
|
+
# An empty array
|
17
|
+
EMPTY_ARRAY = [].freeze
|
18
|
+
# An empty hash
|
19
|
+
EMPTY_HASH = {}.freeze
|
20
|
+
# An empty list of options
|
21
|
+
EMPTY_OPTS = {}.freeze
|
22
|
+
# An empty set
|
23
|
+
EMPTY_SET = Set.new.freeze
|
24
|
+
# An empty string
|
25
|
+
EMPTY_STRING = ''.freeze
|
26
|
+
|
27
|
+
# A special value you can use as a default to know if no arguments
|
28
|
+
# were passed to you method
|
29
|
+
#
|
30
|
+
# @example
|
31
|
+
# def method(value = Undefined)
|
32
|
+
# if value == Undefined
|
33
|
+
# puts 'no args'
|
34
|
+
# else
|
35
|
+
# puts value
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
Undefined = Object.new.tap do |undefined|
|
39
|
+
def undefined.to_s
|
40
|
+
'Undefined'
|
41
|
+
end
|
42
|
+
|
43
|
+
def undefined.inspect
|
44
|
+
'Undefined'
|
45
|
+
end
|
46
|
+
end.freeze
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Dry
|
4
|
+
module Core
|
5
|
+
# An extension for issueing warnings on using deprecated methods.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
#
|
9
|
+
# class Foo
|
10
|
+
# def self.old_class_api; end
|
11
|
+
# def self.new_class_api; end
|
12
|
+
#
|
13
|
+
# deprecate_class_method :old_class_api, :new_class_api
|
14
|
+
#
|
15
|
+
# def old_api; end
|
16
|
+
# def new_api; end
|
17
|
+
#
|
18
|
+
# deprecate_method :old_api, :new_api, "old_api is no-no"
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# @example You also can use this module for your custom messages
|
22
|
+
#
|
23
|
+
# Dry::Core::Deprecations.announce("Foo", "use bar instead")
|
24
|
+
# Dry::Core::Deprecations.warn("Baz is going to be removed soon")
|
25
|
+
#
|
26
|
+
# @api public
|
27
|
+
module Deprecations
|
28
|
+
class << self
|
29
|
+
# Prints a warning
|
30
|
+
#
|
31
|
+
# @param [String] msg Warning string
|
32
|
+
def warn(msg)
|
33
|
+
logger.warn(msg.gsub(/^\s+/, ''))
|
34
|
+
end
|
35
|
+
|
36
|
+
# Wraps arguments with a standard message format and prints a warning
|
37
|
+
#
|
38
|
+
# @param [Object] name what is deprecated
|
39
|
+
# @param [String] msg additional message usually containing upgrade instructions
|
40
|
+
def announce(name, msg)
|
41
|
+
warn(deprecation_message(name, msg))
|
42
|
+
end
|
43
|
+
|
44
|
+
# @api private
|
45
|
+
def deprecation_message(name, msg)
|
46
|
+
<<-MSG
|
47
|
+
#{name} is deprecated and will be removed in the next major version
|
48
|
+
#{message(msg)}
|
49
|
+
MSG
|
50
|
+
end
|
51
|
+
|
52
|
+
# @api private
|
53
|
+
def deprecated_method_message(old, new = nil, msg = nil)
|
54
|
+
if new
|
55
|
+
deprecation_message(old, <<-MSG)
|
56
|
+
Please use #{new} instead.
|
57
|
+
#{msg}
|
58
|
+
MSG
|
59
|
+
else
|
60
|
+
deprecation_message(old, msg)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# @api private
|
65
|
+
def message(msg)
|
66
|
+
<<-MSG
|
67
|
+
#{msg}
|
68
|
+
#{caller.detect { |l| l !~ %r{(lib/dry/core)|(gems)} }}
|
69
|
+
MSG
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns the logger used for printing warnings.
|
73
|
+
# You can provide your own with .set_logger!
|
74
|
+
#
|
75
|
+
# @param [String, Symbol] tag optional prefix for messages
|
76
|
+
# @param [IO] output output stream
|
77
|
+
#
|
78
|
+
# @return [Logger]
|
79
|
+
def logger(tag = nil, output = nil)
|
80
|
+
if defined?(@logger)
|
81
|
+
@logger
|
82
|
+
else
|
83
|
+
set_logger!(output: output, tag: tag)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Sets a custom logger. This is a global settings.
|
88
|
+
#
|
89
|
+
# @option [IO] output output stream for messages
|
90
|
+
# @option [String, Symbol] tag optional prefix
|
91
|
+
#
|
92
|
+
# TODO: Add support for per-module loggers so that at least
|
93
|
+
# tag option won't conflict.
|
94
|
+
def set_logger!(output: nil, tag: nil)
|
95
|
+
@logger = Logger.new(output || $stdout)
|
96
|
+
@logger.formatter = proc { |_severity, _datetime, _progname, msg|
|
97
|
+
"[#{tag || 'deprecated'}] #{msg}\n"
|
98
|
+
}
|
99
|
+
@logger
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Mark instance method as deprecated
|
104
|
+
#
|
105
|
+
# @param [Symbol] old_name deprecated method
|
106
|
+
# @param [Symbol] new_name replacement (not required)
|
107
|
+
# @option [String] message optional deprecation message
|
108
|
+
def deprecate(old_name, new_name = nil, message: nil)
|
109
|
+
full_msg = Deprecations.deprecated_method_message(
|
110
|
+
"#{self.name}##{old_name}",
|
111
|
+
new_name ? "#{self.name}##{new_name}" : nil,
|
112
|
+
message
|
113
|
+
)
|
114
|
+
|
115
|
+
if new_name
|
116
|
+
undef_method old_name
|
117
|
+
define_method(old_name) do |*args, &block|
|
118
|
+
Deprecations.warn(full_msg)
|
119
|
+
__send__(new_name, *args, &block)
|
120
|
+
end
|
121
|
+
else
|
122
|
+
aliased_name = :"#{old_name}_without_deprecation"
|
123
|
+
alias_method aliased_name, old_name
|
124
|
+
private aliased_name
|
125
|
+
undef_method old_name
|
126
|
+
define_method(old_name) do |*args, &block|
|
127
|
+
Deprecations.warn(full_msg)
|
128
|
+
__send__(aliased_name, *args, &block)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Mark class-level method as deprecated
|
134
|
+
#
|
135
|
+
# @param [Symbol] old_name deprecated method
|
136
|
+
# @param [Symbol] new_name replacement (not required)
|
137
|
+
# @option [String] message optional deprecation message
|
138
|
+
def deprecate_class_method(old_name, new_name = nil, message: nil)
|
139
|
+
full_msg = Deprecations.deprecated_method_message(
|
140
|
+
"#{self.name}.#{old_name}",
|
141
|
+
new_name ? "#{self.name}.#{new_name}" : nil,
|
142
|
+
message
|
143
|
+
)
|
144
|
+
|
145
|
+
meth = new_name ? method(new_name) : method(old_name)
|
146
|
+
|
147
|
+
singleton_class.instance_exec do
|
148
|
+
undef_method old_name
|
149
|
+
define_method(old_name) do |*args, &block|
|
150
|
+
Deprecations.warn(full_msg)
|
151
|
+
meth.call(*args, &block)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Dry
|
4
|
+
module Core
|
5
|
+
# Allows to define extensions that can be later enabled by the user.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
#
|
9
|
+
# class Foo
|
10
|
+
# extend Dry::Core::Extensions
|
11
|
+
#
|
12
|
+
# register_extension(:bar) do
|
13
|
+
# def bar; :bar end
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# Foo.new.bar # => NoMethodError
|
18
|
+
# Foo.load_extensions(:bar)
|
19
|
+
# Foo.new.bar # => :bar
|
20
|
+
#
|
21
|
+
module Extensions
|
22
|
+
# @api private
|
23
|
+
def self.extended(obj)
|
24
|
+
super
|
25
|
+
obj.instance_variable_set(:@__available_extensions__, {})
|
26
|
+
obj.instance_variable_set(:@__loaded_extensions__, Set.new)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Register an extension
|
30
|
+
#
|
31
|
+
# @param [Symbol] name extension name
|
32
|
+
# @yield extension block. This block guaranteed not to be called more than once
|
33
|
+
def register_extension(name, &block)
|
34
|
+
@__available_extensions__[name] = block
|
35
|
+
end
|
36
|
+
|
37
|
+
# Enables specified extensions. Already enabled extensions remain untouched
|
38
|
+
#
|
39
|
+
# @param [Array<Symbol>] extensions list of extension names
|
40
|
+
def load_extensions(*extensions)
|
41
|
+
extensions.each do |ext|
|
42
|
+
block = @__available_extensions__.fetch(ext) do
|
43
|
+
raise ArgumentError, "Unknown extension: #{ext.inspect}"
|
44
|
+
end
|
45
|
+
unless @__loaded_extensions__.include?(ext)
|
46
|
+
block.call
|
47
|
+
@__loaded_extensions__ << ext
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dry-core
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nikita Shilnikov
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-09-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: concurrent-ruby
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.12'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.12'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
description: A toolset of small support modules used throughout the dry-rb ecosystem.
|
70
|
+
email:
|
71
|
+
- fg@flashgordon.ru
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".inch.yml"
|
78
|
+
- ".rspec"
|
79
|
+
- ".rubocop.yml"
|
80
|
+
- ".travis.yml"
|
81
|
+
- Gemfile
|
82
|
+
- LICENSE.txt
|
83
|
+
- README.md
|
84
|
+
- Rakefile
|
85
|
+
- dry-core.gemspec
|
86
|
+
- lib/dry-core.rb
|
87
|
+
- lib/dry/core.rb
|
88
|
+
- lib/dry/core/cache.rb
|
89
|
+
- lib/dry/core/class_builder.rb
|
90
|
+
- lib/dry/core/constants.rb
|
91
|
+
- lib/dry/core/deprecations.rb
|
92
|
+
- lib/dry/core/extensions.rb
|
93
|
+
- lib/dry/core/version.rb
|
94
|
+
homepage: https://github.com/dry-rb/dry-code
|
95
|
+
licenses:
|
96
|
+
- MIT
|
97
|
+
metadata:
|
98
|
+
allowed_push_host: https://rubygems.org
|
99
|
+
post_install_message:
|
100
|
+
rdoc_options: []
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
requirements: []
|
114
|
+
rubyforge_project:
|
115
|
+
rubygems_version: 2.5.1
|
116
|
+
signing_key:
|
117
|
+
specification_version: 4
|
118
|
+
summary: A toolset of small support modules used throughout the dry-rb ecosystem.
|
119
|
+
test_files: []
|