modifiers 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c3373d11c2eeb3664593d7252441c0f6df25ae45
4
+ data.tar.gz: 0eafbed86fc457e0f52c461b00631b14436116fa
5
+ SHA512:
6
+ metadata.gz: 40a95f0632d5a9c9ce6e68cc4b033791ce4333d4365653a26559a371f66742e195b44ae7cb2005acb36e632145aa1ace4c89e4b51c3de29e6c1c82d0e80273a1
7
+ data.tar.gz: cd2d9a41929e713c3a84f4b4e0457f2417c890b26e1b87a757839de4ca067ee041a304211516e9ba3fb6457b4b5daf18d27a724440793a58892962fbbd4c4a97
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ .ruby-version
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in modifiers.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 TODO: Write your name
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,224 @@
1
+ ## What is/are Modifiers?
2
+
3
+ `Modifiers` is a collection of method modifiers, and a way to make more.
4
+
5
+ _Method Modifiers_, obviously, are modifiers to methods. Specifically, in Ruby
6
+ terms, they are class methods which:
7
+
8
+ 1. Take a symbol argument which names an instance method of the same class, and
9
+ 2. Return the same symbol, but
10
+ 3. Alter the named method in some way.
11
+
12
+ Ruby has shipped with four (4) modifiers since forever: the three access
13
+ modifiers (`public`, `private`, and `protected`), and `module_function`. This
14
+ library [adds a few others, and a facility for creating even more](#usage).
15
+
16
+ ## Why is/are Modifiers?
17
+
18
+ DRYing up code sometimes involves smaller fragments of shared behavior than a
19
+ method. Here's an example you've probably read and written before:
20
+ ```ruby
21
+ # old and busted
22
+ def count_ducks
23
+ @count_ducks ||= DuckFlock.all.map(&size).inject(0, &:+)
24
+ end
25
+ ```
26
+
27
+ Why are you writing the characters 'count_ducks', in the _exact same order_
28
+ __two whole times__? If you already know how to implement memoization, why let
29
+ your code challenge you to prove it every time you want it done?! Instead,
30
+ implement it one final, flawless time, and tell the interpreter firmly, "No,
31
+ _you_ type the name twice, my time is far too valuable."
32
+
33
+ ## Installation
34
+
35
+ Add this line to your application's Gemfile:
36
+
37
+ gem 'modifiers', require: false
38
+
39
+ And then execute:
40
+
41
+ $ bundle
42
+
43
+ ## Usage
44
+
45
+ ### built-in modifiers
46
+
47
+ #### deprecated
48
+
49
+ Sometimes there's a method, and you want it to die, but not a clean, swift
50
+ death. Instead, you wish it a slow, cursed strangulation, as collaborators
51
+ gradually abandon it. Mark it with your sign, that all may know to shun it or
52
+ be punished.
53
+
54
+ ```ruby
55
+ require 'modifiers/deprecated'
56
+
57
+ class BadHacks
58
+ extend Modifiers
59
+
60
+ deprecated def awful_method
61
+ # some ugly hack, probably involving define_method and ObjectSpace
62
+ end
63
+ end
64
+ ```
65
+
66
+ A method modified by `deprecated` will issue a helpful deprecation warning
67
+ every time it is called. Something like: `deprecated method
68
+ BadHacks#awful_method called from app/controllers/ducks_controller.rb:782`
69
+
70
+ (Please note that the `deprecated` method is deprecated, and you should
71
+ definitely use `Gem.deprecate` instead.)
72
+
73
+ #### memoized
74
+
75
+ Every now and then, you will come to care how long it takes for a method to
76
+ run. You may find yourself wishing it just re-used some hard-won values,
77
+ rather than throwing them away and rebuilding them anew every time you call it.
78
+
79
+ To demonstrate this, on multiple levels, I will re-use the case from a previous
80
+ section.
81
+
82
+ ```ruby
83
+ require 'modifiers/memoized'
84
+
85
+ class DuckService
86
+ extend Modifiers
87
+
88
+ memoized def count_ducks
89
+ DuckFlock.all.map(&size).inject(0, &:+)
90
+ end
91
+ end
92
+ ```
93
+
94
+ A method modified by `memoized` will run once normally, per unique combination
95
+ of arguments, after which it will simply return the same result for the
96
+ lifetime of the receiving object. Dazzle your friends with your terse, yet
97
+ performant, fibonnaci implementations!
98
+
99
+ (If you want all this and more, you can use
100
+ [memoist](https://github.com/matthewrudy/memoist) (formerly
101
+ `ActiveSupport::Memoizable`) instead, but I warn you: it involves `eval`.)
102
+
103
+ #### commands and queries
104
+
105
+ You may have heard of 'Command-Query Separation`, and the claim that code
106
+ quality can be improved by writing methods to either have only side-effects, or
107
+ no side-effects.
108
+
109
+ It may or may not be a good idea, but at least now it's easy to unambiguously
110
+ indicate and enforce!
111
+
112
+ First, a method modified by `command` will always return nil. It's as trivial as it
113
+ sounds.
114
+
115
+ Conversely (?), a method modified by `query` will never change the state of
116
+ anything non-global and in-process. This is also trivial, but it might seem
117
+ more impressive.
118
+ ```ruby
119
+ require 'modifiers/command_query'
120
+
121
+ class DuckFarmer < Struct.new(:hutches)
122
+ extend Modifiers
123
+
124
+ query def fullest_hutch
125
+ hutches.max { |h1,h2| h1.count_eggs - h2.count_eggs
126
+ end
127
+ end
128
+
129
+ class DuckHutch < Struct.new(:num_eggs)
130
+ def self.count_eggs
131
+ @ducks_disturbed = true
132
+ num_eggs
133
+ end
134
+
135
+ def ducks_disturbed?
136
+ @ducks_disturbed
137
+ end
138
+ end
139
+
140
+ john = DuckFarmer.new(Array.new(3) { DuckHutch.new(rand(20)) })
141
+
142
+ john.fullest_hutch # => #<struct DuckHutch num_eggs=11>
143
+
144
+ john.hutches.any? { |h| h.ducks_disturbed? } # => false
145
+ ```
146
+
147
+ If this was an infomercial, now is when I would say something like "It's just
148
+ that easy, Michael!", and you (your name is Michael in this scenario) would say
149
+ "Now _that's_ incredible!" and the audience would applaud.
150
+
151
+ I'm mildly proud of this library.
152
+
153
+ ### defining new modifiers
154
+
155
+ New modifiers can be defined in your own modules using the `define_modifier` method.
156
+
157
+ Let's start with the simplest case: the null modifier, with a name, but no behavior.
158
+
159
+ ```ruby
160
+ require 'modifiers/define_modifier'
161
+
162
+ module DuckFarmModifiers
163
+ extend Modifiers
164
+ define_modifier(:duck)
165
+ end
166
+
167
+ class DuckFarm
168
+ extend DuckFarmModifiers
169
+
170
+ duck :some_method # => unchanged
171
+ end
172
+ ```
173
+
174
+ Here's an identical implementation:
175
+ ```ruby
176
+ module DuckFarmModifiers
177
+ define_modifier(:duck) do |method_invocation|
178
+ method_invocation.invoke
179
+ end
180
+ end
181
+ ```
182
+
183
+ A block passed to `define_modifier` will become the new body of the methods
184
+ modified by the modifier, kinda like with `define_method`.
185
+
186
+ The argument passed to that block will be an object representing a particular
187
+ call to the modified method. As I showed you above, all you have to do
188
+ continue that call as normal is `#invoke` it.
189
+
190
+ Or not!
191
+ ```ruby
192
+ module DuckFarmModifiers
193
+ define_modifier(:x) do
194
+ # temporarily disable a method and see if anyone notices
195
+ end
196
+ end
197
+ ```
198
+
199
+ You can do things before, after, or even "around" the invocation.
200
+ ```ruby
201
+ module DuckFarmModifiers
202
+ define_modifier(:perf_logged) do |invocation|
203
+ start = Time.now
204
+ invocation.invoke
205
+ Rails.logger "#{invocation.method_identifier} finished in #{Time.now - start}s"
206
+ end
207
+ end
208
+ ```
209
+
210
+ The method invocation object can also tell you the `#arguments` in the call,
211
+ and its `#location` in the source, the `#method_name` of the method which was
212
+ modified, or even the full `#method_identifier` in
213
+ `Class.class_method`/`Class#instance_method` style. All of the modifiers
214
+ included in the library were made using it.
215
+
216
+ What awesome ones will _you_ write?
217
+
218
+ ## Contributing
219
+
220
+ 1. [Fork it](https://github.com/nicknovitski/modifiers/fork)
221
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
222
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
223
+ 4. Push to the branch (`git push origin my-new-feature`)
224
+ 5. Create a new Pull Request
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,4 @@
1
+ require 'modifiers/version'
2
+
3
+ module Modifiers
4
+ end
@@ -0,0 +1,8 @@
1
+ require 'modifiers/define_modifier'
2
+
3
+ module Modifiers
4
+ define_modifier(:command) do |invocation|
5
+ invocation.invoke
6
+ nil
7
+ end
8
+ end
@@ -0,0 +1,2 @@
1
+ require 'modifiers/command'
2
+ require 'modifiers/query'
@@ -0,0 +1,11 @@
1
+ require 'modifiers/modification'
2
+
3
+ module Modifiers
4
+ module_function def define_modifier(name, &block)
5
+ define_method(name) do |sym|
6
+ mod = Modification.new(klass: self, method: sym)
7
+ define_method(sym) { |*args| mod.call(self, *args, &block) }
8
+ send(mod.original_visibility, sym)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ require 'modifiers/define_modifier'
2
+
3
+ module Modifiers
4
+ define_modifier(:deprecated) do |invocation|
5
+ warn "deprecated method #{invocation.method_identifier} called from #{invocation.location.join(':')}"
6
+ invocation.invoke
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ require 'modifiers/define_modifier'
2
+
3
+ module Modifiers
4
+ define_modifier(:memoized) do |invocation|
5
+ ivar = "@#{invocation.method_name}".to_sym
6
+
7
+ instance_variable_set(ivar, {}) unless instance_variable_defined?(ivar)
8
+
9
+ memoizer = instance_variable_get(ivar)
10
+ memoizer.fetch(invocation.arguments) { memoizer[invocation.arguments] = invocation.invoke }
11
+ end
12
+ end
@@ -0,0 +1,51 @@
1
+ module Modifiers
2
+ class MethodInvocation
3
+ def initialize(method:, receiver:, arguments:)
4
+ @method = method
5
+ @receiver = receiver
6
+ @arguments = arguments
7
+ end
8
+
9
+ attr_reader :arguments
10
+
11
+ def invoke(context = receiver)
12
+ method.bind(context).call(*arguments)
13
+ end
14
+
15
+ def location
16
+ [file, line_no]
17
+ end
18
+
19
+ def method_name
20
+ method.name
21
+ end
22
+
23
+ def method_identifier
24
+ target + method_name.to_s
25
+ end
26
+
27
+ private
28
+
29
+ def target
30
+ receiver.is_a?(Module) ? "#{receiver}." : "#{receiver.class}#"
31
+ end
32
+
33
+ def file
34
+ match_caller(/(.*?):/i)
35
+ end
36
+
37
+ def line_no
38
+ match_caller(/:(\d+).*?$/i)
39
+ end
40
+
41
+ def match_caller(regex)
42
+ method_caller.match(regex).to_s
43
+ end
44
+
45
+ def method_caller
46
+ caller[7]
47
+ end
48
+
49
+ attr_reader :method, :receiver
50
+ end
51
+ end
@@ -0,0 +1,42 @@
1
+ require 'modifiers/method_invocation'
2
+
3
+ module Modifiers
4
+ class Modification
5
+ def initialize(klass:, method:)
6
+ @klass = klass
7
+ @original_method = klass.send(:instance_method, method)
8
+ @original_visibility = visibility_on(klass)
9
+ end
10
+
11
+ attr_reader :original_visibility
12
+
13
+ def call(instance, *args, &block)
14
+ invocation = MethodInvocation.new(method: original_method, receiver: instance, arguments: args)
15
+ if block
16
+ instance.instance_exec(invocation, &block)
17
+ else
18
+ invocation.invoke
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :original_method, :klass
25
+
26
+ def visibility_on(klass)
27
+ if klass.private_method_defined?(original_method.name)
28
+ :private
29
+ elsif klass.protected_method_defined?(original_method.name)
30
+ :protected
31
+ else
32
+ :public
33
+ end
34
+ end
35
+
36
+ def instance
37
+ klass.new
38
+ rescue TypeError # klass is a singleton metaclass
39
+ ObjectSpace.each_object(klass).first
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,7 @@
1
+ require 'modifiers/define_modifier'
2
+
3
+ module Modifiers
4
+ define_modifier(:query) do |invocation|
5
+ invocation.invoke(Marshal.load(Marshal.dump(self)))
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Modifiers
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'modifiers/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'modifiers'
8
+ spec.version = Modifiers::VERSION
9
+ spec.authors = ['Nick Novitski']
10
+ spec.email = ['nicknovitski@gmail.com']
11
+ spec.summary = 'Cute and Easy method modifiers (also called decorators)'
12
+ spec.description = 'A simple and composable way to add functionality to methods.'
13
+ spec.homepage = 'https://github.com/nicknovitski/modifiers'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.test_files = spec.files.grep(/^spec\//)
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.required_ruby_version = '>= 2.1.0'
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.6'
23
+ spec.add_development_dependency 'rake'
24
+ spec.add_development_dependency "rspec"
25
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ require 'modifiers/command'
3
+
4
+ RSpec.describe Modifiers do
5
+ class Doer
6
+ extend Modifiers
7
+ command def take_action
8
+ # lots of side-effectful-operations
9
+ 2 + 2
10
+ end
11
+ end
12
+
13
+ subject(:doer) { Doer.new }
14
+
15
+ describe '#command' do
16
+ it_behaves_like 'a modifier', :command, changes_return_value: true
17
+
18
+ it 'causes the method to always return nil' do
19
+ expect(doer.take_action).to be_nil
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+ require 'modifiers/define_modifier'
3
+
4
+ module MyModifier
5
+ extend Modifiers
6
+ define_modifier(:bro) { |i| i.invoke + ', bro' }
7
+ end
8
+
9
+ class Foo
10
+ extend MyModifier
11
+
12
+ bro def hello(name = 'world')
13
+ "hello, #{name}"
14
+ end
15
+ end
16
+
17
+ RSpec.describe Modifiers do
18
+ describe '.define_modifier' do
19
+ it 'can make new modifiers in new modules' do
20
+ expect(Foo.new.hello).to eq('hello, world, bro')
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+ require 'modifiers/deprecated'
3
+
4
+ RSpec.describe Modifiers do
5
+ describe '#deprecated' do
6
+ it_behaves_like 'a modifier', :deprecated
7
+
8
+ let(:test_class) do
9
+ class Test
10
+ extend Modifiers
11
+
12
+ deprecated def method
13
+ # something you shouldn't be using
14
+ end
15
+ end
16
+ end
17
+ subject(:test_instance) { test_class.new }
18
+
19
+ around(:example) do |example|
20
+ old_verbose, $VERBOSE = $VERBOSE, nil
21
+ example.call
22
+ $VERBOSE = old_verbose
23
+ end
24
+
25
+ it 'changes the method to warn it has been deprecated' do
26
+ expect(subject).to receive(:warn).with(/deprecated/)
27
+
28
+ subject.method
29
+ end
30
+
31
+ it 'includes the name of the method in the warning' do
32
+ expect(subject).to receive(:warn).with(/Test\#method/)
33
+
34
+ subject.method
35
+ end
36
+
37
+ it 'includes the location of the call in the warning' do
38
+ expect(subject).to receive(:warn).with(/deprecated_spec.rb/)
39
+
40
+ subject.method
41
+ end
42
+
43
+ context 'class methods' do
44
+ before do
45
+ class Test
46
+ class << self
47
+ extend Modifiers
48
+ deprecated def class_method
49
+ #
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ it 'names the method correctly in the warning' do
56
+ expect(test_class).to receive(:warn).with(/Test\.class_method/)
57
+
58
+ test_class.class_method
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+ require 'modifiers/memoized'
3
+
4
+ RSpec.describe Modifiers do
5
+ class Service
6
+ def self.expensive_operation
7
+ 'done'
8
+ end
9
+ end
10
+
11
+ class Client
12
+ extend Modifiers
13
+
14
+ memoized def call_service
15
+ Service.expensive_operation
16
+ end
17
+ end
18
+
19
+ subject(:client) { Client.new }
20
+
21
+ describe '#memoized' do
22
+ it_behaves_like 'a modifier', :memoized
23
+
24
+ it 'prevents execution after the first time' do
25
+ expect(Service).to receive(:expensive_operation).once
26
+
27
+ subject.call_service
28
+ subject.call_service
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+ require 'modifiers/query'
3
+
4
+ RSpec.describe Modifiers do
5
+ class Test
6
+ extend Modifiers
7
+
8
+ def initialize(sub_test = nil)
9
+ @sub_test = sub_test
10
+ @enum = []
11
+ end
12
+
13
+ attr_reader :memo, :enum
14
+
15
+ query def fooer?
16
+ @memo ||= true
17
+ end
18
+
19
+ query def insertable?(val)
20
+ @enum << val
21
+ end
22
+
23
+ query def child_status
24
+ @sub_test.status
25
+ end
26
+ end
27
+
28
+ class SubTest
29
+ def status
30
+ @status ||= :awake
31
+ end
32
+ end
33
+
34
+ let(:child) { SubTest.new }
35
+ subject(:instance) { Test.new(child) }
36
+
37
+ describe '#query' do
38
+ it_behaves_like 'a modifier', :query
39
+
40
+ it "prevents the method from changing the object's instance variables" do
41
+ expect { subject.fooer? }.not_to change { subject.memo }
42
+ end
43
+
44
+ it 'prevents the method from altering arrays' do
45
+ expect { subject.insertable?(:foo) }.not_to change { subject.enum }
46
+ end
47
+
48
+ it 'prevents the method from altering linked objects' do
49
+ expect { instance.child_status }.not_to change { child.instance_variables }
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,48 @@
1
+ RSpec.shared_examples 'a modifier' do |modifier, changes_return_value: false|
2
+ let(:test_class) do
3
+ klass = Class.new do
4
+ extend Modifiers
5
+
6
+ def public_method(arg = :foo)
7
+ arg
8
+ end
9
+
10
+ protected
11
+
12
+ def protected_method
13
+ #
14
+ end
15
+
16
+ private
17
+
18
+ def private_method
19
+ #
20
+ end
21
+ end
22
+ Object.const_set(random_class_name, klass)
23
+ end
24
+ let(:random_class_name) { (0...10).map { ('A'..'Z').to_a[rand(26)] }.join }
25
+ subject(:instance) { test_class.new }
26
+
27
+ unless changes_return_value
28
+ it 'does not change the return value of the method' do
29
+ test_class.send(modifier, :public_method)
30
+ expect(instance.public_method).to be :foo
31
+ expect(instance.public_method(:bar)).to be :bar
32
+ end
33
+ end
34
+
35
+ it 'does not change the visibility of a private method' do
36
+ test_class.send(modifier, :private_method)
37
+ expect(instance.private_methods).to include(:private_method)
38
+ end
39
+
40
+ it 'does not change the visibility of a protected method' do
41
+ test_class.send(modifier, :protected_method)
42
+ expect(instance.protected_methods).to include(:protected_method)
43
+ end
44
+
45
+ it 'does not increase the number of methods on the target' do
46
+ expect { test_class.send(modifier, :public_method) }.not_to change { test_class.methods }
47
+ end
48
+ end
@@ -0,0 +1,12 @@
1
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
2
+ $LOAD_PATH << File.join(APP_ROOT, 'lib')
3
+
4
+ require 'shared_examples_for_modifiers'
5
+
6
+ RSpec.configure do |config|
7
+ config.disable_monkey_patching!
8
+
9
+ config.mock_with :rspec do |mocks|
10
+ mocks.verify_partial_doubles = true
11
+ end
12
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: modifiers
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Nick Novitski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: A simple and composable way to add functionality to methods.
56
+ email:
57
+ - nicknovitski@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - lib/modifiers.rb
68
+ - lib/modifiers/command.rb
69
+ - lib/modifiers/command_query.rb
70
+ - lib/modifiers/define_modifier.rb
71
+ - lib/modifiers/deprecated.rb
72
+ - lib/modifiers/memoized.rb
73
+ - lib/modifiers/method_invocation.rb
74
+ - lib/modifiers/modification.rb
75
+ - lib/modifiers/query.rb
76
+ - lib/modifiers/version.rb
77
+ - modifiers.gemspec
78
+ - spec/modifiers/command_spec.rb
79
+ - spec/modifiers/define_modifier_spec.rb
80
+ - spec/modifiers/deprecated_spec.rb
81
+ - spec/modifiers/memoized_spec.rb
82
+ - spec/modifiers/query_spec.rb
83
+ - spec/shared_examples_for_modifiers.rb
84
+ - spec/spec_helper.rb
85
+ homepage: https://github.com/nicknovitski/modifiers
86
+ licenses:
87
+ - MIT
88
+ metadata: {}
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: 2.1.0
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 2.2.2
106
+ signing_key:
107
+ specification_version: 4
108
+ summary: Cute and Easy method modifiers (also called decorators)
109
+ test_files:
110
+ - spec/modifiers/command_spec.rb
111
+ - spec/modifiers/define_modifier_spec.rb
112
+ - spec/modifiers/deprecated_spec.rb
113
+ - spec/modifiers/memoized_spec.rb
114
+ - spec/modifiers/query_spec.rb
115
+ - spec/shared_examples_for_modifiers.rb
116
+ - spec/spec_helper.rb