directive 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1edf4b07fc8b982911d978b267df2c336f4b0dba62dad286c80ae44a3b280215
4
+ data.tar.gz: 7c1ae7fb109c9ff8261a6f8fda3b4fd15c7eda5682243fe8500ef0a7e75dc9b5
5
+ SHA512:
6
+ metadata.gz: a907b40c95e58500e348cec77ebf864d2e3896ee13edcbe162c01d2b109964db5e056017f3abc9196b5e107c55f9dc374e2753d9e6e32749907a715ebc455ad1
7
+ data.tar.gz: 6cd58b199249b11d00fe6b052d01ac0de6b74f8d879043364b8d2ac9cfce948fdb29d016e6ba27106bc27574d848e3d7572e3386f8e48afb33e8435639b72f1c
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Allen Rettberg
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,39 @@
1
+ # Directive
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/directive`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'directive'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install directive
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ 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.
30
+
31
+ 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).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/directive.
36
+
37
+ ## License
38
+
39
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/lib/directive.rb ADDED
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "directive/config_builder"
4
+ require_relative "directive/config_delegation"
5
+ require_relative "directive/config_object"
6
+ require_relative "directive/evaluator"
7
+ require_relative "directive/reader"
8
+
9
+ # NOTE: This is still a pre-release feature! Use at your own risk - it may change before being released.
10
+ #
11
+ # A utility for creating read-only gem configuration singletons.
12
+ #
13
+ # Usage:
14
+ # # In your gem:
15
+ # module SomeGem
16
+ # module Configuration
17
+ # extend Directive
18
+ #
19
+ # configuration_options do
20
+ # option :some_config_option
21
+ # option :some_option_with_a_default, default: "I probably know what's best"
22
+ #
23
+ # nested :whats_behind do
24
+ # option :door_one, default: "It's a goat"
25
+ # option :door_two, default: "Another goat"
26
+ # option :door_three, default: "It's a car!"
27
+ # end
28
+ # end
29
+ # end
30
+ # end
31
+ #
32
+ # # Then, in the application using the gem:
33
+ # SomeGem::Configuration.configure do |config|
34
+ # config.some_config_option = 12345
35
+ # config.some_option_with_a_default = "Nope, you really don't"
36
+ #
37
+ # config.whats_behind do |nested|
38
+ # nested.door_one = "It's a boat!"
39
+ # nested.door_three = "The teletubbies on repeat 😱"
40
+ # end
41
+ # end
42
+ #
43
+ # # Then, back in your gem code:
44
+ # puts Configuration.config.some_config_option
45
+ # => 12345
46
+ # puts Configuration.config.whats_behind.door_one
47
+ # => "It's a boat!"
48
+ #
49
+ # # Or, if you want to select dynamically:
50
+ # doors = %i[door_one door_two door_three]
51
+ # Configuration.config.config_eval(whats_behind, doors.sample).read
52
+ # => "The teletubbies on repeat 😱"
53
+ module Directive
54
+ delegate :configure, :config_eval, to: :_config_builder
55
+
56
+ # @return [Directive::ConfigReader] A read-only object containing configuration options set inside {#configure}
57
+ def config
58
+ _config_builder.reader
59
+ end
60
+
61
+ # Run a callback before the configure block is evaluated.
62
+ #
63
+ # Note: if configure is called multiple times for your gem, this block will get run each time!
64
+ #
65
+ def before_configure(&block)
66
+ _config_builder_class.set_callback(:configure, :before, &block)
67
+ end
68
+
69
+ # Run a callback after the configure block is evaluated.
70
+ #
71
+ # Note: if configure is called multiple times for your gem, this block will get run each time!
72
+ #
73
+ def after_configure(&block)
74
+ _config_builder_class.set_callback(:configure, :after, &block)
75
+ end
76
+
77
+ private
78
+
79
+ def configuration_options(&block)
80
+ _config_builder.instance_exec(&block)
81
+ end
82
+
83
+ def _config_builder
84
+ @_config_builder ||= _config_builder_class.new
85
+ end
86
+
87
+ def _config_builder_class
88
+ @_config_builder_class ||= Class.new(ConfigBuilder).tap do |klass|
89
+ const_set(:ConfigBuilder, klass)
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "technologic"
4
+ require "active_support/callbacks"
5
+
6
+ require_relative "config_builder/double_configure"
7
+
8
+ module Directive
9
+ class ConfigBuilder
10
+ include ActiveSupport::Callbacks
11
+ define_callbacks :configure
12
+
13
+ # This concern uses the configure callback, so it needs to be included after the callback is defined
14
+ include DoubleConfigure
15
+
16
+ delegate :config_eval, to: :reader
17
+
18
+ def reader
19
+ @reader ||= Reader.new(configuration)
20
+ end
21
+
22
+ def configure
23
+ run_callbacks :configure do
24
+ mutex.synchronize do
25
+ yield configuration
26
+ end
27
+ end
28
+ end
29
+
30
+ # NOTE: options must be set up before {#configure} is called
31
+ def option(*args, &block)
32
+ config_class.__send__(:option, *args, &block)
33
+ end
34
+
35
+ def nested(*args, &block)
36
+ config_class.__send__(:nested, *args, &block)
37
+ end
38
+
39
+ private
40
+
41
+ attr_writer :configure_called
42
+
43
+ def configuration
44
+ config_class.instance
45
+ end
46
+
47
+ def config_class
48
+ @config_class ||= Class.new(ConfigObject)
49
+ end
50
+
51
+ def mutex
52
+ @mutex = Mutex.new
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "technologic"
4
+
5
+ module Directive
6
+ module DoubleConfigure
7
+ extend ActiveSupport::Concern
8
+
9
+ include Technologic
10
+
11
+ included do
12
+ set_callback :configure, :after, :warn_on_multiple_configure_calls
13
+ end
14
+
15
+ private
16
+
17
+ def configure_called?
18
+ @configure_called
19
+ end
20
+
21
+ def warn_on_multiple_configure_calls
22
+ unless configure_called?
23
+ @configure_called = true
24
+ return
25
+ end
26
+
27
+ puts <<~WARNING
28
+ #{self.class._configurable_module_name}.configure has been called more than once, which can lead to unexpected consequences.
29
+ For the most predictable behavior, configure should only be called once.
30
+ WARNING
31
+ end
32
+
33
+ module ClassMethods
34
+ def _configurable_module_name
35
+ name.gsub("::#{name.demodulize}", "")
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Directive
6
+ module ConfigDelegation
7
+ extend ActiveSupport::Concern
8
+
9
+ DEFAULT_CONFIGURATION_MODULE_NAME = "Configuration"
10
+
11
+ module ClassMethods
12
+ delegate :config, :configure, to: :_configuration_module
13
+
14
+ private
15
+
16
+ # Sets up delegation from a top-level class to a nested Configuration module.
17
+ #
18
+ # @example
19
+ # class SomeClass
20
+ # include Spicerack::Configurable::ConfigDelegation
21
+ #
22
+ # delegates_to_configuration
23
+ # end
24
+ #
25
+ # module SomeClass::Configuration
26
+ # include Spicerack::Configurable
27
+ # end
28
+ #
29
+ # SomeClass.config
30
+ # => returns SomeClass::Configuration.config
31
+ # SomeClass.configure do { |config| # config is the yielded config object from SomeClass::Configuration.configure }
32
+ #
33
+ # @param config_class [Spicerack::Configurable] A module that extends Spicerack::Configurable. Defaults to the module +YourGem::Configuration+
34
+ def delegates_to_configuration(config_class = nil)
35
+ @_configuration_module = config_class || "#{self}::#{DEFAULT_CONFIGURATION_MODULE_NAME}".constantize
36
+ end
37
+
38
+ def _configuration_module
39
+ raise NoMethodError, "Configuration not set up for #{self}. Did you forget to call delegates_to_configuration?" if @_configuration_module.nil?
40
+
41
+ @_configuration_module
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Directive
4
+ class ConfigObject < Spicerack::InputObject
5
+ include Singleton
6
+ include ActiveModel::AttributeAssignment
7
+
8
+ alias_method :assign, :assign_attributes
9
+
10
+ RESERVED_WORDS = %i[config_eval].freeze
11
+
12
+ class_attribute :_nested_options, instance_writer: false, default: []
13
+ class_attribute :_nested_builders, instance_writer: false, default: {}
14
+
15
+ class << self
16
+ private
17
+
18
+ def option(name, *)
19
+ _ensure_safe_option_name(name)
20
+
21
+ super
22
+ end
23
+
24
+ def nested(namespace, &block)
25
+ _ensure_safe_option_name(namespace)
26
+
27
+ nested_config_builder_for(namespace).tap do |builder|
28
+ builder.instance_exec(&block)
29
+
30
+ _nested_options << namespace.to_sym
31
+ define_method(namespace) do |&nested_configure_block|
32
+ builder.__send__(:configuration).tap do |nested_config|
33
+ nested_configure_block.call(nested_config) if nested_configure_block.respond_to?(:call)
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ def nested_config_builder_for(namespace)
40
+ _nested_builders[namespace.to_sym] ||= ConfigBuilder.new
41
+ end
42
+
43
+ def _ensure_safe_option_name(name)
44
+ raise ArgumentError, "#{name.inspect} is reserved and cannot be used at a config option" if name.to_sym.in? RESERVED_WORDS
45
+ raise ArgumentError, "#{name.inspect} is already in use" if _nested_options.include?(name.to_sym)
46
+
47
+ puts "Warning: the config option #{name} is already defined" if _options.include?(name.to_sym) # rubocop:disable Rails/Output
48
+ end
49
+
50
+ def inherited(base)
51
+ base._nested_options = _nested_options.dup
52
+ base._nested_builders = _nested_builders.dup
53
+ super
54
+ end
55
+ end
56
+
57
+ def inspect
58
+ "#<#{self.class.superclass} #{super}>"
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Directive
4
+ class Evaluator
5
+ # @param path [Array<Symbol, String>] A message path for the desired config
6
+ # @param configuration [Spicerack::Configurable::Reader]
7
+ def initialize(path, configuration)
8
+ @path = path
9
+ @configuration = configuration
10
+ end
11
+
12
+ def read
13
+ path.inject(configuration, &:public_send)
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :path, :configuration
19
+ end
20
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Directive
4
+ class Reader
5
+ include Tablesalt::StringableObject
6
+
7
+ def initialize(config)
8
+ @config = config
9
+ end
10
+
11
+ def config_eval(*path)
12
+ Evaluator.new(path, self)
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :config
18
+
19
+ def method_missing(method_name, *)
20
+ name = method_name.to_sym
21
+
22
+ return mutex.synchronize { config.public_send(name) } if config._options.map(&:to_sym).include?(name)
23
+ return config._nested_builders[name].reader if config._nested_builders.key?(name)
24
+
25
+ super
26
+ end
27
+
28
+ def respond_to_missing?(method_name, *)
29
+ name = method_name.to_sym
30
+
31
+ config._options.map(&:to_sym).include?(name) ||
32
+ config._nested_builders.key?(name) ||
33
+ super
34
+ end
35
+
36
+ def mutex
37
+ @mutex ||= Mutex.new
38
+ end
39
+
40
+ def stringable_attributes
41
+ config._options + config._nested_options
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "spec_helper/matchers"
4
+ require_relative "spec_helper/dsl"
5
+
6
+ RSpec.configure do |config|
7
+ config.include(Directive::SpecHelper::Matchers::Global)
8
+ config.include(Directive::SpecHelper::Matchers::Configuration, type: :configuration)
9
+ config.include(Directive::SpecHelper::DSL, type: :configuration)
10
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "matchers"
4
+
5
+ module Directive
6
+ module SpecHelper
7
+ module DSL
8
+ def nested_config_option(config_name, &block)
9
+ in_nested_config_stack(config_name) do |nested_stack|
10
+ describe(config_name.to_s, caller: caller) do
11
+ subject { nested_config }
12
+
13
+ let(:parent_config) { parent_config_for_nested(nested_stack) }
14
+ let(:nested_config) { parent_config.public_send(nested_stack.last) }
15
+
16
+ it "defines nested config object #{config_name}" do
17
+ expect(parent_config).to respond_to config_name
18
+ expect(parent_config._nested_options).to include config_name.to_sym
19
+ expect(parent_config.public_send(config_name)).to be_a Spicerack::Configurable::ConfigObject
20
+ end
21
+
22
+ instance_eval(&block)
23
+ end
24
+ end
25
+ end
26
+
27
+ def self.included(base)
28
+ base.extend DSL
29
+ super
30
+ end
31
+
32
+ private
33
+
34
+ def parent_config_for_nested(nested_stack)
35
+ @parent_config ||= {}
36
+
37
+ @parent_config[nested_stack] ||= described_class.
38
+ __send__(:_config_builder).
39
+ __send__(:configuration).
40
+ yield_self do |config|
41
+ nested_stack[0..-2].inject(config) do |conf, nested_name|
42
+ conf.public_send(nested_name)
43
+ end
44
+ end
45
+ end
46
+
47
+ def in_nested_config_stack(name)
48
+ _nested_config_stack << name.to_sym
49
+
50
+ yield _nested_config_stack.dup
51
+
52
+ _nested_config_stack.pop
53
+ end
54
+
55
+ def _nested_config_stack
56
+ Thread.current[:nested_config_stack] ||= []
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Directive
4
+ module SpecHelper
5
+ module Matchers
6
+ module Configuration
7
+ extend ::RSpec::Matchers::DSL
8
+ end
9
+
10
+ module Global
11
+ extend ::RSpec::Matchers::DSL
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ require_relative "matchers/configuration/define_config_option"
18
+ require_relative "matchers/global/delegate_config_to"
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Directive
4
+ module SpecHelper
5
+ module Matchers
6
+ module Configuration
7
+ # RSpec matcher to test options of a Configurable class
8
+ #
9
+ # class ExampleConfiguration
10
+ # include Spicerack::Configurable
11
+ #
12
+ # option :foo
13
+ # option :bar, default: :baz
14
+ # end
15
+ #
16
+ # RSpec.describe ExampleConfiguration, type: :configuration do
17
+ # subject { described_class.new }
18
+ #
19
+ # it { is_expected.to define_config_option :foo }
20
+ # it { is_expected.to define_config_option :bar, default: :baz }
21
+ # end
22
+ define :define_config_option do |option, default: nil|
23
+ description { "define config option #{option.inspect}" }
24
+ failure_message { "expected #{@obj} to define config option #{option.inspect} with default #{default.inspect}" }
25
+
26
+ match do |obj|
27
+ @obj = obj
28
+
29
+ if obj.is_a? Spicerack::Configurable::ConfigObject
30
+ expect(obj).to define_option option, default: default
31
+ else
32
+ expect(obj).to respond_to :config
33
+ expect(obj.config.instance_variable_get(:@config)).to be_present
34
+ expect(obj.config.instance_variable_get(:@config)).to define_option option, default: default
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Directive
4
+ module SpecHelper
5
+ module Matchers
6
+ module Global
7
+ # RSpec matcher to test options of a Configurable class
8
+ #
9
+ # module MyGem
10
+ # include Spicerack::Configurable::ConfigDelegation
11
+ # delegates_to_configuration
12
+ #
13
+ # class MyGem::Configuration
14
+ # include Spicerack::Configurable
15
+ # ...
16
+ # end
17
+ # end
18
+ #
19
+ # RSpec.describe ExampleConfiguration, type: :configuration do
20
+ # subject { described_class }
21
+ #
22
+ # it { is_expected.to delegate_config_to MyGem::Configuration }
23
+ # end
24
+ define :delegate_config_to do |config_module|
25
+ attr_reader :obj, :config_module
26
+
27
+ description { "delegates configuration methods to #{config_module}" }
28
+
29
+ failure_message { "expected #{target} to delegate configuration methods to #{config_module}" }
30
+ failure_message_when_negated { "expected #{target} not to delegate configuration methods to #{config_module}" }
31
+
32
+ match_unless_raises do |obj|
33
+ @obj = obj
34
+ @config_module = config_module
35
+
36
+ stub_configuration_methods
37
+
38
+ expect(target.config).to eq config_return_value
39
+ expect(target.configure).to eq configure_return_value
40
+ end
41
+
42
+ def target
43
+ obj.is_a?(Module) ? obj : obj.class
44
+ end
45
+
46
+ def stub_configuration_methods
47
+ allow(config_module).to receive(:config).and_return(config_return_value)
48
+ allow(config_module).to receive(:configure).and_return(configure_return_value)
49
+ end
50
+
51
+ def config_return_value
52
+ @config_return_value ||= double
53
+ end
54
+
55
+ def configure_return_value
56
+ @configure_return_value ||= double
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Directive
4
+ # This constant is managed by spicerack
5
+ VERSION = "0.22.0"
6
+ end
metadata ADDED
@@ -0,0 +1,179 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: directive
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.22.0
5
+ platform: ruby
6
+ authors:
7
+ - Allen Rettberg
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-01-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 5.2.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 5.2.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.0.1
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 2.0.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: faker
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '1.8'
48
+ - - "<"
49
+ - !ruby/object:Gem::Version
50
+ version: '2.0'
51
+ type: :development
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '1.8'
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '2.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: pry
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 0.10.0
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: 0.10.0
75
+ - !ruby/object:Gem::Dependency
76
+ name: pry-nav
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: 0.2.4
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: 0.2.4
89
+ - !ruby/object:Gem::Dependency
90
+ name: rake
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '10.0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '10.0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: rspec
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '3.0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '3.0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: shoulda-matchers
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - '='
122
+ - !ruby/object:Gem::Version
123
+ version: 4.0.1
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - '='
129
+ - !ruby/object:Gem::Version
130
+ version: 4.0.1
131
+ description: An easy, self-documenting gem configuration framework
132
+ email:
133
+ - allen.rettberg@freshly.com
134
+ executables: []
135
+ extensions: []
136
+ extra_rdoc_files: []
137
+ files:
138
+ - LICENSE.txt
139
+ - README.md
140
+ - lib/directive.rb
141
+ - lib/directive/config_builder.rb
142
+ - lib/directive/config_builder/double_configure.rb
143
+ - lib/directive/config_delegation.rb
144
+ - lib/directive/config_object.rb
145
+ - lib/directive/evaluator.rb
146
+ - lib/directive/reader.rb
147
+ - lib/directive/spec_helper.rb
148
+ - lib/directive/spec_helper/dsl.rb
149
+ - lib/directive/spec_helper/matchers.rb
150
+ - lib/directive/spec_helper/matchers/configuration/define_config_option.rb
151
+ - lib/directive/spec_helper/matchers/global/delegate_config_to.rb
152
+ - lib/directive/version.rb
153
+ homepage: https://github.com/Freshly/spicerack/tree/master/directive
154
+ licenses:
155
+ - MIT
156
+ metadata:
157
+ homepage_uri: https://github.com/Freshly/spicerack/tree/master/directive
158
+ source_code_uri: https://github.com/Freshly/spicerack/blob/master/directive
159
+ changelog_uri: https://github.com/Freshly/spicerack/blob/master/directive/CHANGELOG.md
160
+ post_install_message:
161
+ rdoc_options: []
162
+ require_paths:
163
+ - lib
164
+ required_ruby_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ required_rubygems_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ requirements: []
175
+ rubygems_version: 3.0.3
176
+ signing_key:
177
+ specification_version: 4
178
+ summary: Gem configuration made simple
179
+ test_files: []