proxy_method 0.1.1 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '09fd4847c5a3f98f43e2fa734b759d9ff9ee777c6d2fee717440db40120b7a9b'
4
- data.tar.gz: a989d2beb4ea2c7cb048a483bfa8a32c5ebc4e886c0f502993d0ac27417958dc
3
+ metadata.gz: '07808eb01a4645e80fbde075254b0ae39a7eb4301c5fe035594337f202ab2cbf'
4
+ data.tar.gz: c9b26c4bf4a112d2dbb134e4adac063140b70e26a4fb7ccaac95a0f19687e3f2
5
5
  SHA512:
6
- metadata.gz: 33542c8cc53c3402b5eadcd8cc6ca972f3455219017e16017a3bc9f51f7075ac31fa38736c0c31ac97d6f0a70705509f8cc07b3a1aab997055421d263c114011
7
- data.tar.gz: 4dc532102f028ee2ff996b718312818e72442e93eeb94c4d04435947acc168578218d0d278d3b4914af0d31846e9defbc63eda26d2cad682c6b967218a765163
6
+ metadata.gz: e53e844eb9ad0640f907de886df62fc50550b6a70654eea26eb79a59c8fc1a0670fe0443499d244ed82a84e6c3b0e3e828d950480830bee35c1969c1e8347d10
7
+ data.tar.gz: bbfc055815f09864dcf312b73b76df89062af0a15c66d736aeee2479f23e62164c70e5cc52ada54ca3040b5212113e1036a9449d0efa016a99f5626ff68ba88c
data/README.md CHANGED
@@ -52,10 +52,10 @@ You can do this:
52
52
  Turtle.new.save
53
53
  # => RuntimeError: Disabled by proxy_method
54
54
 
55
- Turtle.proxied_create
55
+ Turtle.unproxied_create
56
56
  # => 'created'
57
57
 
58
- Turtle.new.proxied_save
58
+ Turtle.new.unproxied_save
59
59
  # => 'saved'
60
60
 
61
61
  Specify a custom error message:
@@ -88,12 +88,47 @@ Supply your own prefix for the original, unproxied method:
88
88
  class PrefixPelican < Animal
89
89
  include ProxyMethod
90
90
 
91
- proxy_method :save, prefix: 'pelican'
91
+ proxy_method :save, prefix: 'pelican_'
92
92
  end
93
93
 
94
94
  PrefixPelican.new.pelican_save
95
95
  # => 'saved'
96
96
 
97
+ Use an "unproxied" version of an instance:
98
+
99
+ class DefaultDuck < Animal
100
+ include ProxyMethod
101
+
102
+ proxy_method :save
103
+ end
104
+
105
+ duck = DefaultDuck.new
106
+ duck_unproxied = duck.unproxied
107
+
108
+ duck.save
109
+ # => RunTimeError: Disabled by proxy_method
110
+
111
+ duck_unproxied.save
112
+ # => 'saved'
113
+
114
+
115
+ This is important, because if you proxy a method like `#save` in ActiveRecord,
116
+ you're also preventing the natural use of `#create` and `#update` since these
117
+ rely on `#save` under the hood. "Unproxying" the entire instance then frees
118
+ an interactor to use `#create`, `#update` and `#save` in an intentional way.
119
+
120
+ You can also use an unproxied version of the entire class:
121
+
122
+ duck = DefaultDuck.new
123
+ duck_unproxied = DefaultDuck.unproxied.new
124
+
125
+ duck.save
126
+ # => RunTimeError: Disabled by proxy_method
127
+
128
+ duck_unproxied.save
129
+ # => 'saved'
130
+
131
+
97
132
  ## Installation
98
133
  Add this line to your application's Gemfile:
99
134
 
data/lib/proxy_method.rb CHANGED
@@ -3,30 +3,107 @@ module ProxyMethod
3
3
  DEFAULT_PROXY_MESSAGE = 'Disabled by proxy_method'
4
4
  DEFAULT_PREFIX = 'unproxied_'
5
5
 
6
+ def proxied_instance_methods
7
+ @_proxied_instance_methods ||= {}
8
+ end
9
+
10
+ def proxied_class_methods
11
+ @_proxied_class_methods ||= {}
12
+ end
13
+
14
+ def proxy_class_methods_enabled?
15
+ return @_proxy_class_methods_enabled if defined?(@_proxy_class_methods_enabled)
16
+ @_proxy_class_methods_enabled = true
17
+ end
18
+
6
19
  def proxy_class_method(original_method_names, options = {})
20
+ original_method_names = Array(original_method_names)
21
+
7
22
  error_message = options[:message] || DEFAULT_PROXY_MESSAGE
8
23
  prefix = options[:prefix] || DEFAULT_PREFIX
9
24
 
10
- Array(original_method_names).each do |original_method_name|
11
- self.singleton_class.send(:alias_method, :"#{prefix}#{original_method_name}", original_method_name)
12
- define_singleton_method(original_method_name){ raise error_message }
25
+ original_method_names.each do |original_method_name|
26
+ self.proxied_class_methods.merge!(original_method_name => prefix)
27
+ new_method_name = :"#{prefix}#{original_method_name}"
28
+
29
+ self.singleton_class.send(:alias_method, new_method_name, original_method_name)
30
+ define_singleton_method(original_method_name) do |*args, &block|
31
+ if proxy_class_methods_enabled?
32
+ raise error_message
33
+ else
34
+ send(new_method_name, *args, &block)
35
+ end
36
+ end
13
37
  end
14
38
  end
15
39
 
16
40
  def proxy_instance_method(original_method_names, options = {})
41
+ original_method_names = Array(original_method_names)
42
+
17
43
  error_message = options[:message] || DEFAULT_PROXY_MESSAGE
18
44
  prefix = options[:prefix] || DEFAULT_PREFIX
19
45
 
20
- Array(original_method_names).each do |original_method_name|
21
- alias_method :"#{prefix}#{original_method_name}", original_method_name
22
- define_method(original_method_name){ raise error_message }
46
+ original_method_names.each do |original_method_name|
47
+ self.proxied_instance_methods.merge!(original_method_name => prefix)
48
+ new_method_name = :"#{prefix}#{original_method_name}"
49
+
50
+ alias_method new_method_name, original_method_name
51
+
52
+ define_method(original_method_name) do |*args, &block|
53
+ if proxy_instance_methods_enabled?
54
+ raise error_message
55
+ else
56
+ send(new_method_name, *args, &block)
57
+ end
58
+ end
23
59
  end
24
60
  end
25
61
 
26
62
  alias_method :proxy_method, :proxy_instance_method
63
+
64
+ def unproxied
65
+ self.dup.unproxy!
66
+ end
67
+
68
+ def proxied
69
+ self.dup.proxy!
70
+ end
71
+
72
+ def unproxy!
73
+ @_proxy_class_methods_enabled = false
74
+ self
75
+ end
76
+
77
+ def reproxy!
78
+ @_proxy_class_methods_enabled = true
79
+ self
80
+ end
27
81
  end
28
82
 
29
83
  def self.included(base)
30
84
  base.extend ClassMethods
31
85
  end
86
+
87
+ def proxy_instance_methods_enabled?
88
+ return @_proxy_instance_methods_enabled if defined?(@_proxy_instance_methods_enabled)
89
+ @_proxy_instance_methods_enabled = true
90
+ end
91
+
92
+ def unproxied
93
+ self.dup.unproxy!
94
+ end
95
+
96
+ def proxied
97
+ self.dup.proxy!
98
+ end
99
+
100
+ def unproxy!
101
+ @_proxy_instance_methods_enabled = false
102
+ self
103
+ end
104
+
105
+ def reproxy!
106
+ @_proxy_instance_methods_enabled = true
107
+ self
108
+ end
32
109
  end
@@ -1,3 +1,3 @@
1
1
  module ProxyMethod
2
- VERSION = '0.1.1'
2
+ VERSION = '0.1.2'
3
3
  end
@@ -2,20 +2,28 @@ require 'minitest/autorun'
2
2
  require 'proxy_method'
3
3
 
4
4
  class Animal
5
- def self.create
6
- 'created'
5
+ def self.create target=nil
6
+ ['created', target].compact.join(' ')
7
7
  end
8
8
 
9
9
  def self.destroy_all
10
10
  'destroyed'
11
11
  end
12
12
 
13
+ def self.blocky(first, second)
14
+ yield(first, second)
15
+ end
16
+
13
17
  def save
14
18
  'saved'
15
19
  end
16
20
 
17
- def update
18
- 'updated'
21
+ def update target=nil
22
+ ['updated', target].compact.join(' ')
23
+ end
24
+
25
+ def blocky(first, second)
26
+ yield(first, second)
19
27
  end
20
28
  end
21
29
 
@@ -48,6 +56,12 @@ class PrefixPelican < Animal
48
56
  proxy_method :save, prefix: 'pelican_'
49
57
  end
50
58
 
59
+ class ArgumentativeAardvark < Animal
60
+ include ProxyMethod
61
+
62
+ proxy_method :blocky
63
+ end
64
+
51
65
  class ProxyMethodTest < MiniTest::Test
52
66
  describe "proxying class methods" do
53
67
  it "does not allow original method name to be called" do
@@ -103,6 +117,38 @@ class ProxyMethodTest < MiniTest::Test
103
117
 
104
118
  assert 'created', PrefixPelican.pelican_create
105
119
  end
120
+
121
+ describe "unproxied class" do
122
+ it "allows methods to be called directly" do
123
+ assert_equal 'created feathers', MultiMonkey.unproxied.create('feathers')
124
+
125
+ # ensure that it doesn't affect any other classes
126
+ exception = assert_raises StandardError do
127
+ DefaultDuck.create('feathers')
128
+ end
129
+
130
+ assert_equal "Disabled by proxy_method", exception.message
131
+ end
132
+
133
+ it "handles arguments and blocks" do
134
+ assert_equal 13, ArgumentativeAardvark.unproxied.blocky(6, 7){ |a, b| a + b }
135
+ end
136
+
137
+ it "handles custom prefixes" do
138
+ assert_equal 'created', PrefixPelican.unproxied.create
139
+ end
140
+ end
141
+
142
+ it "leaves the original proxied" do
143
+ duck_unproxied = DefaultDuck.unproxied
144
+ duck_proxied = DefaultDuck
145
+
146
+ assert_equal 'created', duck_unproxied.create
147
+
148
+ assert_raises StandardError do
149
+ duck_proxied.create
150
+ end
151
+ end
106
152
  end
107
153
 
108
154
  describe "proxying instance methods" do
@@ -168,4 +214,36 @@ class ProxyMethodTest < MiniTest::Test
168
214
  assert 'saved', PrefixPelican.new.pelican_save
169
215
  end
170
216
  end
217
+
218
+ describe "unproxied instance" do
219
+ it "allows methods to be called directly" do
220
+ assert_equal 'updated feathers', MultiMonkey.new.unproxied.update('feathers')
221
+
222
+ # ensure that it doesn't affect any other instances
223
+ exception = assert_raises StandardError do
224
+ MultiMonkey.new.update('feathers')
225
+ end
226
+
227
+ assert_equal "Disabled by proxy_method", exception.message
228
+ end
229
+
230
+ it "handles arguments and blocks" do
231
+ assert_equal 13, ArgumentativeAardvark.new.unproxied.blocky(6, 7){ |a, b| a + b }
232
+ end
233
+
234
+ it "handles custom prefixes" do
235
+ assert_equal 'saved', PrefixPelican.new.unproxied.save
236
+ end
237
+
238
+ it "leaves the original proxied" do
239
+ duck_proxied = DefaultDuck.new
240
+ duck_unproxied = duck_proxied.unproxied
241
+
242
+ assert_equal 'saved', duck_unproxied.save
243
+
244
+ assert_raises StandardError do
245
+ duck_proxied.save
246
+ end
247
+ end
248
+ end
171
249
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: proxy_method
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jaime Bellmyer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-18 00:00:00.000000000 Z
11
+ date: 2019-12-19 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |2
14
14
  The purpose of this gem is to prevent directly running the inherited