domesticate_monkeys 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 +7 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +25 -0
- data/MIT-LICENSE +20 -0
- data/README.md +3 -0
- data/bin/domesticate_monkeys +45 -0
- data/lib/domesticate_monkeys/boot/main_app.rb +20 -0
- data/lib/domesticate_monkeys/constants/report.rb +38 -0
- data/lib/domesticate_monkeys/constants/snapshot.rb +42 -0
- data/lib/domesticate_monkeys/constants/track.rb +114 -0
- data/lib/domesticate_monkeys/constants/view.rb +73 -0
- data/lib/domesticate_monkeys/initializers/global_variables.rb +3 -0
- data/lib/domesticate_monkeys/initializers/module.rb +28 -0
- data/lib/domesticate_monkeys/tasks/dm.rake +10 -0
- data/lib/domesticate_monkeys/version.rb +6 -0
- data/lib/domesticate_monkeys.rb +17 -0
- metadata +92 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2b075af4113a94ea0fa6dc9bdbf085b0cad3d0d15b37badffaca05ed77e656d1
|
4
|
+
data.tar.gz: 2f391f15f8044dec6df881f9e81ff5ebd9a034a5ee1b555898a9e240e300070b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 152653bfd024299e8ce20aadda9ded6d8124c754925ba4a532ba30929ec3c8f586c00d5a61227969de12954e4bb4faa16591ec39420d3d2d97370519ce1d9758
|
7
|
+
data.tar.gz: 2cab94b24d90eaa77f9122dbdf7206dbdd5e45bd04e3e4a638a5ce9d651c853927cb2935f3e7631bdb70f661d6a367f7589f35d7ddb26be03bc6d8c45ff4ca1f
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
domesticate_monkeys (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
coderay (1.1.3)
|
10
|
+
method_source (1.0.0)
|
11
|
+
pry (0.14.1)
|
12
|
+
coderay (~> 1.1)
|
13
|
+
method_source (~> 1.0)
|
14
|
+
rake (13.0.6)
|
15
|
+
|
16
|
+
PLATFORMS
|
17
|
+
ruby
|
18
|
+
|
19
|
+
DEPENDENCIES
|
20
|
+
domesticate_monkeys!
|
21
|
+
pry
|
22
|
+
rake
|
23
|
+
|
24
|
+
BUNDLED WITH
|
25
|
+
2.1.4
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2021 Jurriaan Schrofer
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'domesticate_monkeys'
|
3
|
+
require 'pry'
|
4
|
+
|
5
|
+
module DomesticateMonkeys
|
6
|
+
|
7
|
+
options = {}
|
8
|
+
|
9
|
+
# parse task options
|
10
|
+
OptionParser.new do |parser|
|
11
|
+
|
12
|
+
parser.banner = <<~BANNER
|
13
|
+
|
14
|
+
domesticate_monkeys shows you all the method redefinitions within your application and its gems.
|
15
|
+
|
16
|
+
Options:
|
17
|
+
BANNER
|
18
|
+
|
19
|
+
parser.on("-s [SHOW]", "--show [SHOW]", "show view [app, all, overview]") { |view| options[:view] = view }
|
20
|
+
parser.on("-t [COUNT]", "--top [COUNT", "show top x redefinitions") { |top| options[:top] = top }
|
21
|
+
parser.on("-h", "--help", "show option") { puts parser; exit }
|
22
|
+
parser.on("-v", "--version", "show version") { puts VERSION; exit }
|
23
|
+
end.parse!
|
24
|
+
|
25
|
+
# set default arguments
|
26
|
+
view = options[:view]&.to_sym || :app
|
27
|
+
top = options[:top].to_i || 3
|
28
|
+
|
29
|
+
# validate task
|
30
|
+
abort "Aborted: invalid view argument" unless %i( app all overview ).include?(view&.to_sym)
|
31
|
+
abort "Aborted: too many arguments" unless ARGV.empty?
|
32
|
+
|
33
|
+
# load application
|
34
|
+
load MainApp
|
35
|
+
|
36
|
+
# show results
|
37
|
+
dm_view = View.new
|
38
|
+
dm_view.send(view)
|
39
|
+
|
40
|
+
# show reports
|
41
|
+
dm_report = Report.new
|
42
|
+
dm_report.boot_information
|
43
|
+
dm_report.top_redefinitions(top)
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
# Set boot flag
|
3
|
+
$BOOTING_MAIN_APP = true
|
4
|
+
|
5
|
+
# Load required domesticate_monkeys framework
|
6
|
+
require 'bundler'
|
7
|
+
|
8
|
+
# Start boot time counter
|
9
|
+
boot_start = `date`
|
10
|
+
|
11
|
+
# Boot the main application
|
12
|
+
require './config/environment'
|
13
|
+
|
14
|
+
# Finalize boot time counter
|
15
|
+
boot_start = Time.parse(boot_start)
|
16
|
+
boot_end = Time.now
|
17
|
+
$BOOT_TIME = (boot_end.to_f - boot_start.to_f).round(3)
|
18
|
+
|
19
|
+
# Reset boot flag
|
20
|
+
$BOOTING_MAIN_APP = false
|
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
module DomesticateMonkeys
|
3
|
+
class Report
|
4
|
+
|
5
|
+
attr_reader :snapshot, :all_tracks, :multi_tracks, :method_count, :redefined_method_count
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@snapshot = Snapshot.new
|
9
|
+
@all_tracks = @snapshot.all_tracks
|
10
|
+
@multi_tracks = @snapshot.multi_tracks
|
11
|
+
|
12
|
+
@method_count = @all_tracks.size
|
13
|
+
@redefined_method_count = @multi_tracks.size
|
14
|
+
end
|
15
|
+
|
16
|
+
def top_redefinitions(top_amount = 3)
|
17
|
+
puts "Showing top #{top_amount} redefinitions:"
|
18
|
+
tracks = @multi_tracks.first(top_amount).to_h.values
|
19
|
+
tracks.each(&:print)
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def boot_information
|
24
|
+
plain_text = "It took domesticate_monkeys #{$BOOT_TIME} seconds to analyse your application,"\
|
25
|
+
" which defined #{$DOMESTICATE_MONKEYS_COUNT} methods."
|
26
|
+
colored_text = "\e[#{35}m#{plain_text}\e[0m"
|
27
|
+
puts colored_text
|
28
|
+
end
|
29
|
+
|
30
|
+
def inspect
|
31
|
+
# Overwrite default behaviour, which returns – and thus often prints –
|
32
|
+
# the values of the object's set instance variables, which is enormous
|
33
|
+
# in the case of @all_tracks and @multi_tracks.
|
34
|
+
to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
module DomesticateMonkeys
|
3
|
+
class Snapshot
|
4
|
+
|
5
|
+
# The Snapshot class serves as a data storage, which contains, and compartmentalizes,
|
6
|
+
# all current Track instances.
|
7
|
+
|
8
|
+
# The Snapshot's data storage serves as a basis for other classes, such as View (which
|
9
|
+
# provides insight into the data storage), Report (which provides aggregate information
|
10
|
+
# about your application) and TrackExport (which generates a JSON file).
|
11
|
+
|
12
|
+
attr_reader :all_tracks, :filtered_tracks, :multi_tracks
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@all_tracks = $DOMESTICATE_MONKEYS_TRACKS
|
16
|
+
@filtered_tracks = filter_no_methods
|
17
|
+
@multi_tracks = select_multi_tracks
|
18
|
+
end
|
19
|
+
|
20
|
+
def filter_no_methods
|
21
|
+
@all_tracks.filter { _1.include?(".") || _1.include?("#") }
|
22
|
+
end
|
23
|
+
|
24
|
+
def select_multi_tracks
|
25
|
+
multis = @filtered_tracks.select { |_method, track| track.count > 1 }
|
26
|
+
sort_tracks(multis)
|
27
|
+
end
|
28
|
+
|
29
|
+
def sort_tracks(tracks)
|
30
|
+
sorted_array = tracks.sort_by { |_method, track| -track.count }
|
31
|
+
sorted_hash = sorted_array.map { |_method, track| { _method => track } }.inject(&:merge)
|
32
|
+
end
|
33
|
+
|
34
|
+
def inspect
|
35
|
+
# Overwrite default behaviour, which returns – and thus often prints –
|
36
|
+
# the values of the object's set instance variables, which is enormous
|
37
|
+
# in the case of @all_tracks and @multi_tracks.
|
38
|
+
to_s
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require "pry"
|
2
|
+
module DomesticateMonkeys
|
3
|
+
class Track
|
4
|
+
|
5
|
+
# The Track class serves as the main class for tracking all method definitions:
|
6
|
+
# each method, for each object, that gets defined during the initialization
|
7
|
+
# process, gets it's own track with a uniquely identifying key, such as:
|
8
|
+
# 'Nokogiri.scrape', or: 'User#format_name'.
|
9
|
+
|
10
|
+
# The Track instance keeps track of the amount of definitions, the chronological
|
11
|
+
# sequence of the source of the definitions, and potentially other information
|
12
|
+
# which we will deem valuable in the future.
|
13
|
+
|
14
|
+
attr_accessor :method, :count, :sources
|
15
|
+
|
16
|
+
class << self
|
17
|
+
|
18
|
+
def add(unbound_method)
|
19
|
+
|
20
|
+
name = format_method_name(unbound_method)
|
21
|
+
source = read_method_source(unbound_method)
|
22
|
+
return unless name && source
|
23
|
+
|
24
|
+
# Find the existing track for the given method, or create a new track
|
25
|
+
# if the given method is defined for the first time, through the
|
26
|
+
# default value of:
|
27
|
+
# $DOMESTICATE_MONKEYS_TRACKS ||= Hash.new(Track.new)
|
28
|
+
|
29
|
+
# Also, duplicate the found / new record, in order to avoid the same
|
30
|
+
# track being updated all the time and being assigned to all different
|
31
|
+
# keys.
|
32
|
+
|
33
|
+
track = $DOMESTICATE_MONKEYS_TRACKS[name].dup
|
34
|
+
track.add_source(name, source)
|
35
|
+
|
36
|
+
rescue
|
37
|
+
return
|
38
|
+
end
|
39
|
+
|
40
|
+
def format_method_name(unbound_method)
|
41
|
+
|
42
|
+
# The formatted method name serves as the uniquely identifying key for
|
43
|
+
# all operations, with a distinguishing '#' for instance methods and a
|
44
|
+
# '.' for singleton methods.
|
45
|
+
|
46
|
+
name = unbound_method.to_s
|
47
|
+
|
48
|
+
return format_instance_method(name) if name.include?('UnboundMethod')
|
49
|
+
return format_singleton_method(name) if name.include?('Method')
|
50
|
+
end
|
51
|
+
|
52
|
+
def format_instance_method(name)
|
53
|
+
name.slice(/(?<=#<UnboundMethod: )[^(]*/)
|
54
|
+
.gsub(/\(.*\)/,'')
|
55
|
+
.delete('>')
|
56
|
+
end
|
57
|
+
|
58
|
+
def format_singleton_method(name)
|
59
|
+
name.slice(/(?<=#<Method: )[^(]*/)
|
60
|
+
.gsub(/\(.*\)/,'')
|
61
|
+
.delete('>')
|
62
|
+
end
|
63
|
+
|
64
|
+
def read_method_source(unbound_method)
|
65
|
+
unbound_method.source_location&.join(':')
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
def initialize
|
71
|
+
@method = nil
|
72
|
+
@count = 0
|
73
|
+
@sources = []
|
74
|
+
end
|
75
|
+
|
76
|
+
def add_source(method_name, source)
|
77
|
+
|
78
|
+
$DOMESTICATE_MONKEYS_COUNT += 1
|
79
|
+
printf("\r Methods defined: #{$DOMESTICATE_MONKEYS_COUNT}\r") if $BOOTING_MAIN_APP
|
80
|
+
|
81
|
+
@method ||= method_name
|
82
|
+
|
83
|
+
# Duplicate the retrieved self.sources, in order to avoid the instance variable
|
84
|
+
# from hanging and being stacked with every new source – shared between multiple
|
85
|
+
# instances.
|
86
|
+
dupped_sources = @sources.dup
|
87
|
+
|
88
|
+
# Only add a source to the sources variable if the method is being redefined, i.e.
|
89
|
+
# being defined by source code that differs from the previously held definition.
|
90
|
+
# If a file is being read for a second time, the method is technically defined again
|
91
|
+
# but not redefined, since all behaviour is still the same. Therefore we should not
|
92
|
+
# track such cases.
|
93
|
+
dupped_sources << source unless dupped_sources.last == source
|
94
|
+
|
95
|
+
# Update the tracker's state, and add it to our global $DOMESTICATE_MONKEYS_TRACKS dictionary afterwards.
|
96
|
+
@sources = dupped_sources
|
97
|
+
@count = dupped_sources.size
|
98
|
+
|
99
|
+
$DOMESTICATE_MONKEYS_TRACKS[self.method] = self
|
100
|
+
end
|
101
|
+
|
102
|
+
def print
|
103
|
+
view = <<~EOL
|
104
|
+
|
105
|
+
#{@count} definitions for:
|
106
|
+
#{@method}
|
107
|
+
#{@sources.map.with_index { |source, i| "#{i}: #{source}"}.join("\n")}
|
108
|
+
EOL
|
109
|
+
|
110
|
+
puts view
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
|
2
|
+
module DomesticateMonkeys
|
3
|
+
class View
|
4
|
+
|
5
|
+
attr_reader :snapshot
|
6
|
+
|
7
|
+
def initialize(snapshot = nil)
|
8
|
+
@snapshot = snapshot || Snapshot.new
|
9
|
+
end
|
10
|
+
|
11
|
+
# parsed CLI option methods
|
12
|
+
|
13
|
+
def all(path_filter = nil)
|
14
|
+
tracks = @snapshot.multi_tracks
|
15
|
+
tracks = filter_tracks_by_path(tracks, path_filter) if path_filter
|
16
|
+
|
17
|
+
tracks.values.each { |track| track.print }
|
18
|
+
|
19
|
+
# Return nil in order to avoid a lengthy print of the @snapshot.
|
20
|
+
return nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def app
|
24
|
+
all(app_name)
|
25
|
+
end
|
26
|
+
|
27
|
+
def overview
|
28
|
+
app_header = header_text("#{app_monkeys_count} Monkeys within our own application").red
|
29
|
+
puts app_header
|
30
|
+
app
|
31
|
+
|
32
|
+
all_header = header_text("#{all_monkeys_count} Monkeys through the whole application, including third party software").yellow
|
33
|
+
puts all_header
|
34
|
+
all
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# Helper methods
|
40
|
+
|
41
|
+
def filter_tracks_by_path(tracks, path_filter)
|
42
|
+
tracks.select do |_method, track|
|
43
|
+
track.sources.any? { |source| source.snakecase.include?(path_filter.snakecase) }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def app_name
|
48
|
+
app_class = Rails.application.class
|
49
|
+
# Support both the new Module#module_parent and the deprecated Module#parent methods (Rails 6.1)
|
50
|
+
top_class = app_class.respond_to?(:module_parent) ? app_class.module_parent : app_class.parent
|
51
|
+
app_name = top_class.name.snakecase
|
52
|
+
end
|
53
|
+
|
54
|
+
def app_monkeys_count
|
55
|
+
filter_tracks_by_path(@snapshot.multi_tracks, app_name).count
|
56
|
+
end
|
57
|
+
|
58
|
+
def all_monkeys_count
|
59
|
+
@snapshot.multi_tracks.count
|
60
|
+
end
|
61
|
+
|
62
|
+
def header_text(text)
|
63
|
+
<<~EOL
|
64
|
+
|
65
|
+
|
66
|
+
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
|
67
|
+
#{text}
|
68
|
+
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
|
69
|
+
EOL
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
class Module
|
3
|
+
|
4
|
+
# We can keep track of all methods through the two patches below, which are
|
5
|
+
# provided by ruby as useful callbacks.
|
6
|
+
|
7
|
+
# In order to track as much methods and redefinitions as possible, and thus
|
8
|
+
# giving the best representation of your application's method defining
|
9
|
+
# process, we should initialize all tracker relevant classes AND the below
|
10
|
+
# callbacks as early on in the initialization process as possible.
|
11
|
+
|
12
|
+
# Although 'the earlier, the better' does definitely apply, this should, in
|
13
|
+
# any case, happen BEFORE the initialization of Rails and all other gems.
|
14
|
+
# The reason being that we can only track redefinitions of methods defined in
|
15
|
+
# gems, such as Rails, if we first are able to built a Track for that method's
|
16
|
+
# orignal definition.
|
17
|
+
|
18
|
+
def method_added(_method)
|
19
|
+
unbound_method = instance_method(_method)
|
20
|
+
DomesticateMonkeys::Track.add(unbound_method)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.singleton_method_added(_method)
|
24
|
+
unbound_method = singleton_method(_method)
|
25
|
+
DomesticateMonkeys::Track.add(unbound_method)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
require "domesticate_monkeys/version"
|
3
|
+
|
4
|
+
module DomesticateMonkeys
|
5
|
+
|
6
|
+
Root = File.expand_path('../', __dir__)
|
7
|
+
MainApp = Root + "/lib/domesticate_monkeys/boot/main_app.rb"
|
8
|
+
|
9
|
+
autoload :Track, "domesticate_monkeys/constants/track"
|
10
|
+
autoload :View, "domesticate_monkeys/constants/view"
|
11
|
+
autoload :Snapshot, "domesticate_monkeys/constants/snapshot"
|
12
|
+
autoload :Report, "domesticate_monkeys/constants/report"
|
13
|
+
|
14
|
+
require "domesticate_monkeys/initializers/global_variables"
|
15
|
+
require "domesticate_monkeys/initializers/module"
|
16
|
+
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: domesticate_monkeys
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jurriaan Schrofer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-10-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
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: pry
|
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
|
+
description: Monkey patches make your application great yet dangerous, therefore you
|
42
|
+
ought to domesticate them!
|
43
|
+
email:
|
44
|
+
- jschrofer@gmail.com
|
45
|
+
executables:
|
46
|
+
- domesticate_monkeys
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- Gemfile
|
51
|
+
- Gemfile.lock
|
52
|
+
- MIT-LICENSE
|
53
|
+
- README.md
|
54
|
+
- bin/domesticate_monkeys
|
55
|
+
- lib/domesticate_monkeys.rb
|
56
|
+
- lib/domesticate_monkeys/boot/main_app.rb
|
57
|
+
- lib/domesticate_monkeys/constants/report.rb
|
58
|
+
- lib/domesticate_monkeys/constants/snapshot.rb
|
59
|
+
- lib/domesticate_monkeys/constants/track.rb
|
60
|
+
- lib/domesticate_monkeys/constants/view.rb
|
61
|
+
- lib/domesticate_monkeys/initializers/global_variables.rb
|
62
|
+
- lib/domesticate_monkeys/initializers/module.rb
|
63
|
+
- lib/domesticate_monkeys/tasks/dm.rake
|
64
|
+
- lib/domesticate_monkeys/version.rb
|
65
|
+
homepage: https://github.com/jurriaanschrofer/domesticate_monkeys
|
66
|
+
licenses:
|
67
|
+
- MIT
|
68
|
+
metadata:
|
69
|
+
homepage_uri: https://github.com/jurriaanschrofer/domesticate_monkeys
|
70
|
+
source_code_uri: https://github.com/jurriaanschrofer/domesticate_monkeys
|
71
|
+
changelog_uri: https://github.com/jurriaanschrofer/domesticate_monkeys
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubygems_version: 3.0.9
|
88
|
+
signing_key:
|
89
|
+
specification_version: 4
|
90
|
+
summary: Monkey patches make your application great yet dangerous, therefore you ought
|
91
|
+
to domesticate them!
|
92
|
+
test_files: []
|