modifiers 0.0.2 → 1.0.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 +4 -4
- data/.rspec +1 -0
- data/.travis.yml +9 -1
- data/README.md +4 -1
- data/lib/modifiers/command.rb +2 -2
- data/lib/modifiers/define_modifier.rb +5 -5
- data/lib/modifiers/deprecated.rb +31 -3
- data/lib/modifiers/memoized.rb +21 -5
- data/lib/modifiers/modification.rb +20 -34
- data/lib/modifiers/query.rb +25 -2
- data/lib/modifiers/version.rb +1 -1
- data/modifiers.gemspec +1 -1
- data/spec/modifiers/command_spec.rb +2 -1
- data/spec/modifiers/define_modifier_spec.rb +27 -3
- data/spec/modifiers/deprecated_spec.rb +28 -21
- data/spec/modifiers/memoized_spec.rb +2 -1
- data/spec/modifiers/query_spec.rb +11 -5
- metadata +15 -15
- data/lib/modifiers/method_invocation.rb +0 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1362dad9adfb0a9ac28f10588f0f233f00472038
|
4
|
+
data.tar.gz: 22c39749a7f5ae6c411754899ae57db54fd7e52a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3bebfb125f3104c010eb94e4ee1b9de4c40cdeec0f9f542c45d5cb074631a4b3ef93f86ba7b07d6391d16387fb6db8d479144d0ba37e5baa671cabe483b6c9f0
|
7
|
+
data.tar.gz: 27007ced57e661678ceba35749a1cdad47c764375cafeab094482626677a8a547cda788209a145fc21ae12449161cf520ec78f7da2d05f9a0b76d359f08666b3
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--order rand
|
data/.travis.yml
CHANGED
@@ -1,5 +1,13 @@
|
|
1
|
-
|
1
|
+
language: ruby
|
2
2
|
rvm:
|
3
|
+
- 2.0.0
|
3
4
|
- 2.1.0
|
4
5
|
- 2.1.1
|
5
6
|
- 2.1.2
|
7
|
+
deploy:
|
8
|
+
provider: rubygems
|
9
|
+
api_key:
|
10
|
+
secure: fewAgjCXLYSkbRq57EQYRTjwPn/LfQgpvSh1HBdVG1Vjds2OCL+yl3d6x30o4q28GU7dMLKjEl2BZrrQ9TwPgit3LRPUwlsoZRvGQj+oztdNfshpWansne6coBYa5vx/tQFBSDWkTMdE2RMH1w7qP20Iqn44c4yQU1tQiqWoZMQ=
|
11
|
+
on:
|
12
|
+
tags: true
|
13
|
+
repo: nicknovitski/modifiers
|
data/README.md
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
# Modifiers
|
2
|
+
[](https://travis-ci.org/nicknovitski/modifiers)
|
3
|
+
|
1
4
|
## What is/are Modifiers?
|
2
5
|
|
3
6
|
`Modifiers` is a collection of method modifiers, and a way to make more.
|
@@ -122,7 +125,7 @@ class DuckFarmer < Struct.new(:hutches)
|
|
122
125
|
extend Modifiers
|
123
126
|
|
124
127
|
query def fullest_hutch
|
125
|
-
hutches.max { |h1,h2| h1.count_eggs - h2.count_eggs
|
128
|
+
hutches.max { |h1,h2| h1.count_eggs - h2.count_eggs }
|
126
129
|
end
|
127
130
|
end
|
128
131
|
|
data/lib/modifiers/command.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'modifiers/modification'
|
2
2
|
|
3
3
|
module Modifiers
|
4
|
-
def define_modifier(
|
5
|
-
define_method(
|
6
|
-
mod = Modification.new(
|
7
|
-
|
8
|
-
|
4
|
+
def define_modifier(modifier, helper = nil, &method_body)
|
5
|
+
define_method(modifier) do |modified|
|
6
|
+
mod = Modification.new(modifier, self, modified, method_body)
|
7
|
+
mod.send(:include, helper) if helper
|
8
|
+
prepend mod
|
9
9
|
end
|
10
10
|
end
|
11
11
|
module_function :define_modifier
|
data/lib/modifiers/deprecated.rb
CHANGED
@@ -1,8 +1,36 @@
|
|
1
1
|
require 'modifiers/define_modifier'
|
2
2
|
|
3
3
|
module Modifiers
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
module Deprecated
|
5
|
+
private
|
6
|
+
|
7
|
+
def kaller
|
8
|
+
caller[4]
|
9
|
+
end
|
10
|
+
|
11
|
+
def file
|
12
|
+
match_caller(/(.*?):/i)
|
13
|
+
end
|
14
|
+
|
15
|
+
def line
|
16
|
+
match_caller(/:(\d+).*?$/i)
|
17
|
+
end
|
18
|
+
|
19
|
+
def match_caller(pattern)
|
20
|
+
kaller.match(pattern)[1].to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
def location
|
24
|
+
[file, line].join(':')
|
25
|
+
end
|
26
|
+
|
27
|
+
def target
|
28
|
+
is_a?(Module) ? "#{self}." : "#{self.class}#"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
define_modifier(:deprecated, Deprecated) do |*args, &block|
|
33
|
+
warn "deprecated method #{target}#{__method__} called from #{location}"
|
34
|
+
super(*args, &block)
|
7
35
|
end
|
8
36
|
end
|
data/lib/modifiers/memoized.rb
CHANGED
@@ -1,12 +1,28 @@
|
|
1
1
|
require 'modifiers/define_modifier'
|
2
2
|
|
3
3
|
module Modifiers
|
4
|
-
|
5
|
-
|
4
|
+
module Memoized
|
5
|
+
private
|
6
6
|
|
7
|
-
|
7
|
+
def ivar(method_name)
|
8
|
+
"@#{method_name}".to_sym
|
9
|
+
end
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
+
def init_memo(method_name)
|
12
|
+
instance_variable_set(ivar(method_name), {}) unless instance_variable_defined?(ivar(method_name))
|
13
|
+
end
|
14
|
+
|
15
|
+
def memoizer_for(method_name)
|
16
|
+
instance_variable_get(ivar(method_name))
|
17
|
+
end
|
18
|
+
|
19
|
+
def memoizer_fetch(method_name, key, &block)
|
20
|
+
memoizer_for(method_name).fetch(key, &block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
define_modifier(:memoized, Memoized) do |*args, &block|
|
25
|
+
init_memo(__method__)
|
26
|
+
memoizer_fetch(__method__, args) { memoizer_for(__method__)[args] = super(*args, &block) }
|
11
27
|
end
|
12
28
|
end
|
@@ -1,42 +1,28 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
1
|
+
class Modification < Module
|
2
|
+
def initialize(name, receiver, method_name, method_body)
|
3
|
+
@name, @receiver, @method_name = name, receiver, method_name
|
4
|
+
super() do
|
5
|
+
define_method(method_name, &method_body)
|
6
|
+
set_visibility
|
20
7
|
end
|
8
|
+
end
|
21
9
|
|
22
|
-
|
10
|
+
private
|
23
11
|
|
24
|
-
|
12
|
+
attr_reader :receiver, :method_name
|
25
13
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
:protected
|
31
|
-
else
|
32
|
-
:public
|
33
|
-
end
|
14
|
+
def set_visibility
|
15
|
+
case
|
16
|
+
when private? then private(method_name)
|
17
|
+
when protected? then protected(method_name)
|
34
18
|
end
|
19
|
+
end
|
35
20
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
21
|
+
def protected?
|
22
|
+
receiver.protected_method_defined?(method_name)
|
23
|
+
end
|
24
|
+
|
25
|
+
def private?
|
26
|
+
receiver.private_method_defined?(method_name)
|
41
27
|
end
|
42
28
|
end
|
data/lib/modifiers/query.rb
CHANGED
@@ -1,7 +1,30 @@
|
|
1
1
|
require 'modifiers/define_modifier'
|
2
2
|
|
3
3
|
module Modifiers
|
4
|
-
|
5
|
-
|
4
|
+
module Querying
|
5
|
+
def ivars_hash
|
6
|
+
instance_variables.each_with_object({}) do |ivar, hash|
|
7
|
+
hash[ivar] = instance_variable_get(ivar)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def duplicate_ivars!
|
12
|
+
ivars_hash.each { |k,v| instance_variable_set(k, Marshal.load(Marshal.dump(v))) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def set_ivars(hash)
|
16
|
+
hash.each { |k, v| instance_variable_set(k, v) }
|
17
|
+
|
18
|
+
in_state_but_not_hash = instance_variables.select { |i| hash[i].nil? }
|
19
|
+
in_state_but_not_hash.each { |i| remove_instance_variable(i) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
define_modifier(:query, Querying) do |*args, &block|
|
24
|
+
orig_ivars = ivars_hash
|
25
|
+
duplicate_ivars!
|
26
|
+
return_value = super(*args, &block)
|
27
|
+
set_ivars(orig_ivars)
|
28
|
+
return_value
|
6
29
|
end
|
7
30
|
end
|
data/lib/modifiers/version.rb
CHANGED
data/modifiers.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.test_files = spec.files.grep(/^spec\//)
|
18
18
|
spec.require_paths = ['lib']
|
19
19
|
|
20
|
-
spec.required_ruby_version = '>= 2.
|
20
|
+
spec.required_ruby_version = '>= 2.0.0'
|
21
21
|
|
22
22
|
spec.add_development_dependency 'bundler', '~> 1.6'
|
23
23
|
spec.add_development_dependency 'rake'
|
@@ -3,21 +3,45 @@ require 'modifiers/define_modifier'
|
|
3
3
|
|
4
4
|
module MyModifier
|
5
5
|
extend Modifiers
|
6
|
-
define_modifier(:bro)
|
6
|
+
define_modifier(:bro) do |*args, &block|
|
7
|
+
super(*args, &block) + ', bro'
|
8
|
+
end
|
9
|
+
|
10
|
+
module Watch
|
11
|
+
private
|
12
|
+
|
13
|
+
def timestamp
|
14
|
+
Time.now
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
define_modifier(:timed, Watch) do |*args, &block|
|
19
|
+
super(*args, &block) + "(#{__method__} called at #{timestamp})"
|
20
|
+
end
|
7
21
|
end
|
8
22
|
|
9
23
|
class Foo
|
10
24
|
extend MyModifier
|
11
25
|
|
12
|
-
|
26
|
+
def hello(name = 'world')
|
13
27
|
"hello, #{name}"
|
14
28
|
end
|
29
|
+
bro :hello
|
30
|
+
|
31
|
+
def poot
|
32
|
+
"I accidentally typed the name of this method but I think it's great"
|
33
|
+
end
|
34
|
+
timed :poot
|
15
35
|
end
|
16
36
|
|
17
37
|
RSpec.describe Modifiers do
|
18
38
|
describe '.define_modifier' do
|
19
39
|
it 'can make new modifiers in new modules' do
|
20
|
-
expect(Foo.new.hello).to eq('hello,
|
40
|
+
expect(Foo.new.hello('modified')).to eq('hello, modified, bro')
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'can include helper modules' do
|
44
|
+
expect(Foo.new.poot).to match(/\(poot called at/)
|
21
45
|
end
|
22
46
|
end
|
23
47
|
end
|
@@ -3,41 +3,47 @@ require 'modifiers/deprecated'
|
|
3
3
|
|
4
4
|
RSpec.describe Modifiers do
|
5
5
|
describe '#deprecated' do
|
6
|
-
|
6
|
+
context "with silenced warnings" do
|
7
|
+
around(:example) do |example|
|
8
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
9
|
+
example.call
|
10
|
+
$VERBOSE = old_verbose
|
11
|
+
end
|
7
12
|
|
8
|
-
|
9
|
-
|
10
|
-
extend Modifiers
|
13
|
+
it_behaves_like 'a modifier', :deprecated
|
14
|
+
end
|
11
15
|
|
12
|
-
|
13
|
-
|
14
|
-
|
16
|
+
class Test
|
17
|
+
extend Modifiers
|
18
|
+
|
19
|
+
def method
|
20
|
+
# something you shouldn't be using
|
15
21
|
end
|
22
|
+
deprecated :method
|
16
23
|
end
|
17
|
-
subject(:test_instance) { test_class.new }
|
18
24
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
25
|
+
subject(:test_instance) do
|
26
|
+
s = Test.new
|
27
|
+
allow(s).to receive(:warn)
|
28
|
+
s
|
23
29
|
end
|
24
30
|
|
25
31
|
it 'changes the method to warn it has been deprecated' do
|
26
|
-
expect(subject).to receive(:warn).with(/deprecated/)
|
27
|
-
|
28
32
|
subject.method
|
33
|
+
|
34
|
+
expect(subject).to have_received(:warn).with(/deprecated/)
|
29
35
|
end
|
30
36
|
|
31
37
|
it 'includes the name of the method in the warning' do
|
32
|
-
expect(subject).to receive(:warn).with(/Test\#method/)
|
33
|
-
|
34
38
|
subject.method
|
39
|
+
|
40
|
+
expect(subject).to have_received(:warn).with(/Test\#method/)
|
35
41
|
end
|
36
42
|
|
37
43
|
it 'includes the location of the call in the warning' do
|
38
|
-
expect(subject).to receive(:warn).with(/deprecated_spec.rb/)
|
39
|
-
|
40
44
|
subject.method
|
45
|
+
|
46
|
+
expect(subject).to have_received(:warn).with(/deprecated_spec.rb/)
|
41
47
|
end
|
42
48
|
|
43
49
|
context 'class methods' do
|
@@ -45,17 +51,18 @@ RSpec.describe Modifiers do
|
|
45
51
|
class Test
|
46
52
|
class << self
|
47
53
|
extend Modifiers
|
48
|
-
|
54
|
+
def class_method
|
49
55
|
#
|
50
56
|
end
|
57
|
+
deprecated :class_method
|
51
58
|
end
|
52
59
|
end
|
53
60
|
end
|
54
61
|
|
55
62
|
it 'names the method correctly in the warning' do
|
56
|
-
expect(
|
63
|
+
expect(Test).to receive(:warn).with(/Test\.class_method/)
|
57
64
|
|
58
|
-
|
65
|
+
Test.class_method
|
59
66
|
end
|
60
67
|
end
|
61
68
|
end
|
@@ -12,22 +12,28 @@ RSpec.describe Modifiers do
|
|
12
12
|
|
13
13
|
attr_reader :memo, :enum
|
14
14
|
|
15
|
-
|
15
|
+
def fooer?
|
16
16
|
@memo ||= true
|
17
17
|
end
|
18
|
+
query :fooer?
|
18
19
|
|
19
|
-
|
20
|
+
def insertable?(val)
|
20
21
|
@enum << val
|
21
22
|
end
|
23
|
+
query :insertable?
|
22
24
|
|
23
|
-
|
25
|
+
def child_status
|
24
26
|
@sub_test.status
|
25
27
|
end
|
28
|
+
query :child_status
|
26
29
|
end
|
27
30
|
|
28
31
|
class SubTest
|
32
|
+
def initialize
|
33
|
+
@state_changes = []
|
34
|
+
end
|
29
35
|
def status
|
30
|
-
@
|
36
|
+
@state_changes << :awake
|
31
37
|
end
|
32
38
|
end
|
33
39
|
|
@@ -46,7 +52,7 @@ RSpec.describe Modifiers do
|
|
46
52
|
end
|
47
53
|
|
48
54
|
it 'prevents the method from altering linked objects' do
|
49
|
-
expect { instance.child_status }.not_to change { child.
|
55
|
+
expect { instance.child_status }.not_to change { child.instance_variable_get(:@state_changes) }
|
50
56
|
end
|
51
57
|
end
|
52
58
|
end
|
metadata
CHANGED
@@ -1,55 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: modifiers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Novitski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-09-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.6'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.6'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - '>='
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
description: A simple and composable way to add functionality to methods.
|
@@ -59,8 +59,9 @@ executables: []
|
|
59
59
|
extensions: []
|
60
60
|
extra_rdoc_files: []
|
61
61
|
files:
|
62
|
-
-
|
63
|
-
-
|
62
|
+
- .gitignore
|
63
|
+
- .rspec
|
64
|
+
- .travis.yml
|
64
65
|
- Gemfile
|
65
66
|
- LICENSE.txt
|
66
67
|
- README.md
|
@@ -71,7 +72,6 @@ files:
|
|
71
72
|
- lib/modifiers/define_modifier.rb
|
72
73
|
- lib/modifiers/deprecated.rb
|
73
74
|
- lib/modifiers/memoized.rb
|
74
|
-
- lib/modifiers/method_invocation.rb
|
75
75
|
- lib/modifiers/modification.rb
|
76
76
|
- lib/modifiers/query.rb
|
77
77
|
- lib/modifiers/version.rb
|
@@ -93,17 +93,17 @@ require_paths:
|
|
93
93
|
- lib
|
94
94
|
required_ruby_version: !ruby/object:Gem::Requirement
|
95
95
|
requirements:
|
96
|
-
- -
|
96
|
+
- - '>='
|
97
97
|
- !ruby/object:Gem::Version
|
98
|
-
version: 2.
|
98
|
+
version: 2.0.0
|
99
99
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - '>='
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
requirements: []
|
105
105
|
rubyforge_project:
|
106
|
-
rubygems_version: 2.
|
106
|
+
rubygems_version: 2.0.14
|
107
107
|
signing_key:
|
108
108
|
specification_version: 4
|
109
109
|
summary: Cute and Easy method modifiers (also called decorators)
|
@@ -1,51 +0,0 @@
|
|
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
|