proxy_method 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/README.md +118 -0
- data/Rakefile +8 -0
- data/lib/proxy_method.rb +32 -0
- data/lib/proxy_method/version.rb +3 -0
- data/test/test_proxy_method.rb +171 -0
- metadata +54 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d326c1e11ed5cd4cc667d4687a7290d0fb157284a51d19a8fbf08ba1f97c65cf
|
4
|
+
data.tar.gz: 986f2c19ece82f97e8f28c6d846f14661e2ba400d28983f28ce04c786052bcb9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: da246a3fd150d0f55649db524a7b0f68205aaaa59885b382b42ee3fb8705512e0093138760a827f677401483778c5dda94d1a87982171216a47e34f91813261e
|
7
|
+
data.tar.gz: daefa8c60fe9e5bf4f29cac4cf87ae8aaf80e1c4f9f7fef4ef91d3a3a7e699d883b8990ce7a294901bbd08ec9643897e0f03a3d56b4f774382320c08a9e34156
|
data/README.md
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# proxy_method
|
2
|
+
|
3
|
+
Prevent running an inherited method directly.
|
4
|
+
|
5
|
+
The purpose of this gem is to prevent directly running the inherited
|
6
|
+
methods you choose to block, and instead raise a custom Error message.
|
7
|
+
The original method can still be called under a different name.
|
8
|
+
|
9
|
+
This was created to help enforce the use of interactors over directly
|
10
|
+
calling ActiveRecord methods like create, save, and update. One downside
|
11
|
+
of interactors is that they require top-of-mind awareness in order to use
|
12
|
+
them, and by default new/forgetful/overworked developers will create
|
13
|
+
ActiveRecord instances all willy nilly until society crumbles.
|
14
|
+
|
15
|
+
While this was created for ActiveRecord models specifically, it works
|
16
|
+
with *any* inherited methods. The method being proxied has to already
|
17
|
+
exist, or it can't be overridden.
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Given these basic classes:
|
22
|
+
|
23
|
+
class Animal
|
24
|
+
def self.create
|
25
|
+
'created'
|
26
|
+
end
|
27
|
+
|
28
|
+
def save
|
29
|
+
'saved'
|
30
|
+
end
|
31
|
+
|
32
|
+
def update
|
33
|
+
'updated'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Turtle < Animal
|
38
|
+
include ProxyMethod
|
39
|
+
|
40
|
+
proxy_class_method :create
|
41
|
+
proxy_instance_method :save
|
42
|
+
|
43
|
+
# for instance methods, you can also just call "proxy_method"
|
44
|
+
proxy_method :update
|
45
|
+
end
|
46
|
+
|
47
|
+
You can do this:
|
48
|
+
|
49
|
+
Turtle.create
|
50
|
+
# => RuntimeError: Disabled by proxy_method
|
51
|
+
|
52
|
+
Turtle.new.save
|
53
|
+
# => RuntimeError: Disabled by proxy_method
|
54
|
+
|
55
|
+
Turtle.proxied_create
|
56
|
+
# => 'created'
|
57
|
+
|
58
|
+
Turtle.new.proxied_save
|
59
|
+
# => 'saved'
|
60
|
+
|
61
|
+
Specify a custom error message:
|
62
|
+
|
63
|
+
class CustomCow < Animal
|
64
|
+
include ProxyMethod
|
65
|
+
|
66
|
+
proxy_method :save, message: "Don't save here, use an interactor!"
|
67
|
+
end
|
68
|
+
|
69
|
+
CustomCow.new.save
|
70
|
+
# => RunTimeError: Don't save here, use an interactor!
|
71
|
+
|
72
|
+
Specify multiple methods at once:
|
73
|
+
|
74
|
+
class MultiMonkey < Animal
|
75
|
+
include ProxyMethod
|
76
|
+
|
77
|
+
proxy_method [:save, :update], message: "Use an interactor!"
|
78
|
+
end
|
79
|
+
|
80
|
+
MultiMonkey.new.save
|
81
|
+
# => RunTimeError: Use an interactor!
|
82
|
+
|
83
|
+
MultiMonkey.new.update
|
84
|
+
# => RunTimeError: Use an interactor!
|
85
|
+
|
86
|
+
Supply your own prefix for the original, unproxied method:
|
87
|
+
|
88
|
+
class PrefixPelican < Animal
|
89
|
+
include ProxyMethod
|
90
|
+
|
91
|
+
proxy_method :save, prefix: 'pelican'
|
92
|
+
end
|
93
|
+
|
94
|
+
PrefixPelican.new.pelican_save
|
95
|
+
# => 'saved'
|
96
|
+
|
97
|
+
## Installation
|
98
|
+
Add this line to your application's Gemfile:
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
gem 'proxy_method'
|
102
|
+
```
|
103
|
+
|
104
|
+
And then execute:
|
105
|
+
```bash
|
106
|
+
$ bundle
|
107
|
+
```
|
108
|
+
|
109
|
+
Or install it yourself as:
|
110
|
+
```bash
|
111
|
+
$ gem install proxy_method
|
112
|
+
```
|
113
|
+
|
114
|
+
## Contributing
|
115
|
+
Feel free to fork and create a pull request.
|
116
|
+
|
117
|
+
## License
|
118
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/lib/proxy_method.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module ProxyMethod
|
2
|
+
module ClassMethods
|
3
|
+
DEFAULT_PROXY_MESSAGE = 'Disabled by proxy_method'
|
4
|
+
DEFAULT_PREFIX = 'unproxied_'
|
5
|
+
|
6
|
+
def proxy_class_method(original_method_names, options = {})
|
7
|
+
error_message = options[:message] || DEFAULT_PROXY_MESSAGE
|
8
|
+
prefix = options[:prefix] || DEFAULT_PREFIX
|
9
|
+
|
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 }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def proxy_instance_method(original_method_names, options = {})
|
17
|
+
error_message = options[:message] || DEFAULT_PROXY_MESSAGE
|
18
|
+
prefix = options[:prefix] || DEFAULT_PREFIX
|
19
|
+
|
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 }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
alias_method :proxy_method, :proxy_instance_method
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.included(base)
|
30
|
+
base.extend ClassMethods
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'proxy_method'
|
3
|
+
|
4
|
+
class Animal
|
5
|
+
def self.create
|
6
|
+
'created'
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.destroy_all
|
10
|
+
'destroyed'
|
11
|
+
end
|
12
|
+
|
13
|
+
def save
|
14
|
+
'saved'
|
15
|
+
end
|
16
|
+
|
17
|
+
def update
|
18
|
+
'updated'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Turtle < Animal
|
23
|
+
include ProxyMethod
|
24
|
+
|
25
|
+
proxy_class_method :create, message: "Don't Create directly, use Interactor!"
|
26
|
+
proxy_instance_method :update, message: "Don't Update directly, use Interactor!"
|
27
|
+
proxy_method :save, message: "Don't Save directly, use Interactor!"
|
28
|
+
end
|
29
|
+
|
30
|
+
class DefaultDuck < Animal
|
31
|
+
include ProxyMethod
|
32
|
+
|
33
|
+
proxy_class_method :create
|
34
|
+
proxy_method :save
|
35
|
+
end
|
36
|
+
|
37
|
+
class MultiMonkey < Animal
|
38
|
+
include ProxyMethod
|
39
|
+
|
40
|
+
proxy_class_method [:create, :destroy_all]
|
41
|
+
proxy_method [:save, :update]
|
42
|
+
end
|
43
|
+
|
44
|
+
class PrefixPelican < Animal
|
45
|
+
include ProxyMethod
|
46
|
+
|
47
|
+
proxy_class_method :create, prefix: 'pelican_'
|
48
|
+
proxy_method :save, prefix: 'pelican_'
|
49
|
+
end
|
50
|
+
|
51
|
+
class ProxyMethodTest < MiniTest::Test
|
52
|
+
describe "proxying class methods" do
|
53
|
+
it "does not allow original method name to be called" do
|
54
|
+
exception = assert_raises StandardError do
|
55
|
+
Turtle.create
|
56
|
+
end
|
57
|
+
|
58
|
+
assert_equal "Don't Create directly, use Interactor!", exception.message
|
59
|
+
end
|
60
|
+
|
61
|
+
it "allows proxied method name to be called" do
|
62
|
+
assert 'created', Turtle.unproxied_create
|
63
|
+
end
|
64
|
+
|
65
|
+
it "does not confuse proxied class method with instance method" do
|
66
|
+
assert_raises NoMethodError do
|
67
|
+
Turtle.save
|
68
|
+
end
|
69
|
+
|
70
|
+
assert_raises NoMethodError do
|
71
|
+
Turtle.unproxied_save
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it "provides default error message" do
|
76
|
+
exception = assert_raises StandardError do
|
77
|
+
DefaultDuck.create
|
78
|
+
end
|
79
|
+
|
80
|
+
assert_equal "Disabled by proxy_method", exception.message
|
81
|
+
end
|
82
|
+
|
83
|
+
it "allows for multiple methods to be proxied in one call" do
|
84
|
+
exception = assert_raises StandardError do
|
85
|
+
MultiMonkey.create
|
86
|
+
end
|
87
|
+
|
88
|
+
assert_equal "Disabled by proxy_method", exception.message
|
89
|
+
|
90
|
+
exception = assert_raises StandardError do
|
91
|
+
MultiMonkey.destroy_all
|
92
|
+
end
|
93
|
+
|
94
|
+
assert_equal "Disabled by proxy_method", exception.message
|
95
|
+
end
|
96
|
+
|
97
|
+
it "allows for a custom prefix" do
|
98
|
+
exception = assert_raises StandardError do
|
99
|
+
PrefixPelican.create
|
100
|
+
end
|
101
|
+
|
102
|
+
assert_equal "Disabled by proxy_method", exception.message
|
103
|
+
|
104
|
+
assert 'created', PrefixPelican.pelican_create
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "proxying instance methods" do
|
109
|
+
it "does not allow original method name to be called" do
|
110
|
+
exception = assert_raises StandardError do
|
111
|
+
Turtle.new.save
|
112
|
+
end
|
113
|
+
|
114
|
+
assert_equal "Don't Save directly, use Interactor!", exception.message
|
115
|
+
end
|
116
|
+
|
117
|
+
it "allows proxied method name to be called" do
|
118
|
+
assert 'saved', Turtle.new.unproxied_save
|
119
|
+
end
|
120
|
+
|
121
|
+
it "does not confuse proxied class method with instance method" do
|
122
|
+
assert_raises NoMethodError do
|
123
|
+
Turtle.new.create
|
124
|
+
end
|
125
|
+
|
126
|
+
assert_raises NoMethodError do
|
127
|
+
Turtle.new.unproxied_create
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
it "aliases proxy_method to proxy_instance_method" do
|
132
|
+
exception = assert_raises StandardError do
|
133
|
+
Turtle.new.update
|
134
|
+
end
|
135
|
+
|
136
|
+
assert_equal "Don't Update directly, use Interactor!", exception.message
|
137
|
+
end
|
138
|
+
|
139
|
+
it "provides default error message" do
|
140
|
+
exception = assert_raises StandardError do
|
141
|
+
DefaultDuck.new.save
|
142
|
+
end
|
143
|
+
|
144
|
+
assert_equal "Disabled by proxy_method", exception.message
|
145
|
+
end
|
146
|
+
|
147
|
+
it "allows for multiple methods to be proxied in one call" do
|
148
|
+
exception = assert_raises StandardError do
|
149
|
+
MultiMonkey.new.save
|
150
|
+
end
|
151
|
+
|
152
|
+
assert_equal "Disabled by proxy_method", exception.message
|
153
|
+
|
154
|
+
exception = assert_raises StandardError do
|
155
|
+
MultiMonkey.new.update
|
156
|
+
end
|
157
|
+
|
158
|
+
assert_equal "Disabled by proxy_method", exception.message
|
159
|
+
end
|
160
|
+
|
161
|
+
it "allows for a custom prefix" do
|
162
|
+
exception = assert_raises StandardError do
|
163
|
+
PrefixPelican.new.save
|
164
|
+
end
|
165
|
+
|
166
|
+
assert_equal "Disabled by proxy_method", exception.message
|
167
|
+
|
168
|
+
assert 'saved', PrefixPelican.new.pelican_save
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: proxy_method
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jaime Bellmyer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-12-18 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: |2
|
14
|
+
The purpose of this gem is to prevent directly running the inherited
|
15
|
+
methods you choose to block, and instead raise a custom Error message.
|
16
|
+
The original method can still be called under a different name.
|
17
|
+
|
18
|
+
This was created to help enforce the use of interactors over directly
|
19
|
+
calling ActiveRecord methods like create, save, and update.
|
20
|
+
email:
|
21
|
+
- online@bellmyer.com
|
22
|
+
executables: []
|
23
|
+
extensions: []
|
24
|
+
extra_rdoc_files: []
|
25
|
+
files:
|
26
|
+
- README.md
|
27
|
+
- Rakefile
|
28
|
+
- lib/proxy_method.rb
|
29
|
+
- lib/proxy_method/version.rb
|
30
|
+
- test/test_proxy_method.rb
|
31
|
+
homepage: https://rubygems.org/gems/proxy_method
|
32
|
+
licenses:
|
33
|
+
- MIT
|
34
|
+
metadata: {}
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
requirements: []
|
50
|
+
rubygems_version: 3.0.1
|
51
|
+
signing_key:
|
52
|
+
specification_version: 4
|
53
|
+
summary: Prevent running an inherited method directly
|
54
|
+
test_files: []
|