safe_monkeypatch 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 844de048f173e6086d969251524d92a7c31ed3ba
4
+ data.tar.gz: f96cd2f537e8060d2772adb966e85dd3a06daee5
5
+ SHA512:
6
+ metadata.gz: dab778853b53dc6c4f0c7fc4407779b85b47cfb5d30bae151ad465909ce5a17ef4cb5c6966e5d9296ac7983dfbe9d4d9ced54946e3e607b6691f59dd472c12d0
7
+ data.tar.gz: 6e5b91d0cb0058944fdd263a898da8a2f35fb7bb02bc217ff5fcdd5db334aab96c87851d0b16f8e8aa3ba7277df88021bc9bcc829a50b88f00f1914c46e5134a
data/.gitignore ADDED
@@ -0,0 +1,22 @@
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
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.1
6
+ - jruby-19mode
7
+ - rbx
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in safe_monkeypatch.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Vlad Bokov
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.
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # SafeMonkeypatch
2
+
3
+ [![Gem Version][GV img]][Gem Version]
4
+ [![Build Status][BS img]][Build Status]
5
+
6
+ **If you can, please, DO NOT monkeypatch.**
7
+
8
+ Sometimes I patch ActiveRecord, but ain't sure if
9
+ it's gonna break in the next version of Rails. This gem
10
+ would raise an error if monkey patched method has changed
11
+ since last time you've adapted your patch to the upstream.
12
+
13
+ ## Usage
14
+
15
+ # assume some upstream in foo.gem:
16
+ class Foo
17
+ def bar
18
+ puts "do first thing"
19
+ puts "do second thing"
20
+ puts "do something else"
21
+ end
22
+ end
23
+
24
+ # your code
25
+ class Foo
26
+
27
+ # you can use any of Digest::*** checksum's methods: sha1, etc.
28
+ # NOTE: do this BEFORE monkeypatch happens
29
+ safe_monkeypatch :bar, md5: "", error: "my additional info for exception"
30
+
31
+ def bar
32
+ puts "do first thing"
33
+ # puts "do second thing" # don't do that
34
+ puts "do something else"
35
+ end
36
+ end
37
+
38
+ Until upstream code isn't changed, it's working like usual.
39
+ But if the new version changes the implementation of `Foo#bar` method, an
40
+ error is raised **while startup time**
41
+ (unless you monkeypatch in runtime, but now you're on your own):
42
+
43
+ SafeMonkeypatch::UpstreamChanged: Foo#bar expected to have md5 checksum: "", but has: ""
44
+ my additional info for exception
45
+
46
+ You can also use it without patched module scope (for proper error use patched class/module name):
47
+
48
+ Foo.safe_monkeypatch Foo.instance_method(:bar), md5: 'invalid_checksum'
49
+
50
+ Happy monkeypatching :)
51
+
52
+ [Gem Version]: https://rubygems.org/gems/safe_monkeypatch
53
+ [Build Status]: https://travis-ci.org/razum2um/safe_monkeypatch
54
+
55
+ [GV img]: https://badge.fury.io/rb/safe_monkeypatch.png
56
+ [BS img]: https://travis-ci.org/razum2um/safe_monkeypatch.png
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require 'bundler/setup'
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
8
+
@@ -0,0 +1,47 @@
1
+ require "digest"
2
+ require "method_source"
3
+
4
+ module SafeMonkeypatch
5
+ extend self
6
+
7
+ class UpstreamChanged < StandardError
8
+ end
9
+
10
+ class ConfigurationError < StandardError
11
+ end
12
+
13
+ class InvalidMethod < StandardError
14
+ end
15
+ end
16
+
17
+ class Module
18
+ def safe_monkeypatch(meth, options={})
19
+ options = options.dup
20
+ info = options.delete(:error)
21
+
22
+ if meth.is_a? UnboundMethod
23
+ method = meth
24
+ meth = method.name
25
+ else
26
+ begin
27
+ method = instance_method(meth)
28
+ rescue NameError => e
29
+ raise SafeMonkeypatch::InvalidMethod, "#{inspect} has no method #{meth} anymore"
30
+ end
31
+ end
32
+
33
+ source = method.source
34
+
35
+ if options.empty?
36
+ raise SafeMonkeypatch::ConfigurationError, "Provide at least one cypher name like: md5: '...'"
37
+ end
38
+
39
+ options.each do |cypher_name, expected|
40
+ cypher = Digest.const_get(cypher_name.upcase)
41
+ if (actual = cypher.hexdigest(source)) != expected
42
+ raise SafeMonkeypatch::UpstreamChanged, "#{inspect}##{meth} expected to have #{cypher_name} expected: '#{expected}', but has: '#{actual}'\n#{info}".strip
43
+ end
44
+ end
45
+ end
46
+ end
47
+
@@ -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
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "safe_monkeypatch"
7
+ spec.version = "0.0.1"
8
+ spec.authors = ["Vlad Bokov"]
9
+ spec.email = ["razum2um@mail.ru"]
10
+ spec.summary = %q{Patch methods without fear!}
11
+ spec.description = %q{Checksums method source and raises if upstream has changed.}
12
+ spec.homepage = "https://github.com/razum2um/safe_monkeypatch"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "method_source"
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,76 @@
1
+ require 'spec_helper'
2
+
3
+ MD5_CHECKSUM = 'b1c5ef3149e6e0062e1c21c3ce8af7d8'
4
+
5
+ RSpec.describe SafeMonkeypatch do
6
+ subject { Foo.new }
7
+
8
+ before do
9
+ class Foo
10
+ def bar
11
+ "bar"
12
+ end
13
+ end
14
+ end
15
+
16
+ it "works as usual" do
17
+ class Foo
18
+ safe_monkeypatch :bar, md5: MD5_CHECKSUM
19
+
20
+ def bar
21
+ "patched bar"
22
+ end
23
+ end
24
+
25
+ expect(subject.bar).to eq "patched bar"
26
+ end
27
+
28
+ it 'raises if none cypher is given' do
29
+ expect {
30
+ class Foo
31
+ safe_monkeypatch :bar
32
+
33
+ def bar
34
+ "patch!"
35
+ end
36
+ end
37
+ }.to raise_error SafeMonkeypatch::ConfigurationError
38
+ end
39
+
40
+ it "raises if method disappear" do
41
+ expect {
42
+ class Foo
43
+ undef :bar
44
+ safe_monkeypatch :bar, md5: MD5_CHECKSUM
45
+
46
+ def bar
47
+ "patched disappeared"
48
+ end
49
+ end
50
+ }.to raise_error SafeMonkeypatch::InvalidMethod
51
+ end
52
+
53
+ it "raises if method has changed" do
54
+ expect {
55
+ class Foo
56
+ safe_monkeypatch :bar, md5: 'invalid_checksum'
57
+
58
+ def bar
59
+ "patched changed"
60
+ end
61
+ end
62
+ }.to raise_error(
63
+ SafeMonkeypatch::UpstreamChanged,
64
+ /Foo#bar expected to have md5 expected: 'invalid_checksum', but has: '#{MD5_CHECKSUM}'/
65
+ )
66
+ end
67
+
68
+ it "accepts custom UnboundMethod" do
69
+ expect {
70
+ Foo.safe_monkeypatch Foo.instance_method(:bar), md5: 'another_checksum'
71
+ }.to raise_error(
72
+ SafeMonkeypatch::UpstreamChanged,
73
+ /Foo#bar expected to have md5 expected: 'another_checksum', but has: '#{MD5_CHECKSUM}'/
74
+ )
75
+ end
76
+ end
@@ -0,0 +1,23 @@
1
+ require "safe_monkeypatch"
2
+
3
+ RSpec.configure do |config|
4
+ config.filter_run :focus
5
+ config.run_all_when_everything_filtered = true
6
+
7
+ if config.files_to_run.one?
8
+ config.default_formatter = 'doc'
9
+ end
10
+
11
+ config.order = :random
12
+ Kernel.srand config.seed
13
+
14
+ config.expect_with :rspec do |expectations|
15
+ expectations.syntax = :expect
16
+ end
17
+
18
+ config.mock_with :rspec do |mocks|
19
+ mocks.syntax = :expect
20
+ mocks.verify_partial_doubles = true
21
+ end
22
+ end
23
+
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: safe_monkeypatch
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Vlad Bokov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: method_source
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
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
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Checksums method source and raises if upstream has changed.
70
+ email:
71
+ - razum2um@mail.ru
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".travis.yml"
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - lib/safe_monkeypatch.rb
84
+ - safe_monkeypatch.gemspec
85
+ - spec/safe_monkeypatch_spec.rb
86
+ - spec/spec_helper.rb
87
+ homepage: https://github.com/razum2um/safe_monkeypatch
88
+ licenses:
89
+ - MIT
90
+ metadata: {}
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 2.2.2
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: Patch methods without fear!
111
+ test_files:
112
+ - spec/safe_monkeypatch_spec.rb
113
+ - spec/spec_helper.rb