duck_puncher 4.4.2 → 5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 62f4cac1d15e159d6ba58d71681cec7e34be8c71
4
- data.tar.gz: 53ee95a89344c33f8960cf5d957cbb5dbf6d3562
2
+ SHA256:
3
+ metadata.gz: d1fcb68e87edfbb74d3a7c6d1d3699e4d636825096d63a4bd0ebf5084e159bf8
4
+ data.tar.gz: f5ef839a1ee7c73bf22ede9d831142b4d68b97de1c0581269c798e2a86732603
5
5
  SHA512:
6
- metadata.gz: ea6d68c9efd49449907ccfb6aab5b810f6b0081ce399817afc78804a813cf0c66feea9ea0cfe74492e3b1091baa3011cc0cc1492d2bdb2ed6ca5e27433f9e9eb
7
- data.tar.gz: dd5bf802c09382798460d26c81650588f10f64de8e2cba77fec53d82e55fffb932fe785178233037d96965b53b9093c7088e2c2f87c608c23828df71f81b05c8
6
+ metadata.gz: 19cc97cf751f1bd1bd2b140da0ecc267b02832ddfbd5ce165682409e575c233784fd4f45035e320d254965dedb933f6726473b5d1f2e34d0aa98abdf6fabd2f5
7
+ data.tar.gz: d17270cbdb1634ead0c15e3c24238eeea6b50270fc5e01371a28bc60c9aeaaa007852ab5f385620b99707087cf8b1165d9b7a9fe8de6677710d0a8fd6943ed66
data/duck_puncher.gemspec CHANGED
@@ -13,16 +13,16 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = "https://github.com/ridiculous/duck_puncher"
14
14
  spec.license = "MIT"
15
15
 
16
- spec.files = `git ls-files`.split($/)
16
+ spec.files = `git ls-files`.split($/).keep_if { |f| f =~ /duck_puncher/ and f !~ %r{test/} }
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.test_files = spec.files.grep(%r{^(test)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.required_ruby_version = ">= 2.0.0"
22
22
 
23
23
  spec.add_runtime_dependency "usable", ">= 3.3"
24
24
 
25
- spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "bundler", ">= 1.3"
26
26
  spec.add_development_dependency "rake", '~> 10.1'
27
27
  spec.add_development_dependency "minitest", '~> 5.0'
28
28
  spec.add_development_dependency "minitest-reporters", '~> 1.1'
data/lib/duck_puncher.rb CHANGED
@@ -23,7 +23,7 @@ module DuckPuncher
23
23
 
24
24
  class << self
25
25
  # @description Include additional functionality
26
- include Registration # [:register, :deregister]
26
+ include Registration # [:register, :register!, :deregister]
27
27
  include Decoration # [:decorators, :build_decorator_class, :decorate, :cached_decorators, :undecorate]
28
28
  include Utilities # [:lookup_constant, :redefine_constant]
29
29
  include AncestralHash # [:ancestral_hash]
@@ -62,6 +62,14 @@ module DuckPuncher
62
62
  @punched_ducks ||= Set.new
63
63
  end
64
64
 
65
+ # Register an extension with a target class
66
+ # When given a block, the block is used to create an anonymous module
67
+ # @param target [Class,Module,Object] constant or instance to extend
68
+ # @param mods [Array<Module>] modules to extend or mix into the target. The last argument can be a hash of options to customize the extension
69
+ # @option :only [Symbol, Array<Symbol>] list of methods to extend onto the target (the module must have these defined)
70
+ # @option :method [Symbol,String] the method used to apply the module, e.g. :extend (:include)
71
+ # @option :before [Proc] A hook that is called with the target class before #punch
72
+ # @option :after [Proc] A hook that is called with the target class after #punch
65
73
  def register(*)
66
74
  target, *_ = super
67
75
  decorators[target] = build_decorator_class(*Ducks[target])
@@ -24,5 +24,5 @@ ducks = [
24
24
  ]
25
25
  ducks << [ActiveRecord::Base, DuckPuncher::Ducks::ActiveRecord] if defined?(Rails) && defined?(ActiveRecord) && defined?(ActiveRecord::Base)
26
26
  ducks.each do |duck|
27
- DuckPuncher.register *duck
27
+ DuckPuncher.register(*duck)
28
28
  end
@@ -5,6 +5,8 @@ module DuckPuncher
5
5
  # @param target [String,Class] Class or module to punch
6
6
  # @param mod [String,Module] The module that defines the extensions
7
7
  # @param [Hash] options to modify the duck #punch method behavior
8
+ # @option options :only [Symbol, Array<Symbol>] list of methods to extend onto the target (the module must have these defined)
9
+ # @option options :method [Symbol,String] the method used to apply the module, e.g. :extend (:include)
8
10
  # @option options :before [Proc] A hook that is called with the target class before +punch+
9
11
  # @option options :after [Proc] A hook that is called with the target class after +punch+
10
12
  def initialize(target, mod, options = {})
@@ -14,9 +16,9 @@ module DuckPuncher
14
16
  end
15
17
 
16
18
  # @param [Hash] opts to modify punch
17
- # @option options [Class] :target Specifies the class to be punched
18
- # @option options [Array,Symbol] :only Specifies the methods to extend onto the current object
19
- # @option options [Symbol,String] :method Specifies if the methods should be included or prepended (:include)
19
+ # @option options :target [Class] Specifies the class to be punched (overrides @target)
20
+ # @option options :only [Array,Symbol] Specifies the methods to extend onto the current object
21
+ # @option options :method [Symbol,String] Specifies if the methods should be included or prepended (:include)
20
22
  # @return [Class] The class that was just punched
21
23
  def call(opts = {})
22
24
  opts = options.merge(opts)
@@ -1,50 +1,57 @@
1
1
  module DuckPuncher
2
- module Ducks
3
- module ActiveRecord
4
- def self.included(base)
5
- base.extend(ClassMethods)
6
- end
7
-
8
- def associations?
9
- associations.present?
10
- end
11
-
12
- def associations
13
- reflections.select { |key, _| send(key).present? rescue nil }.keys
14
- end
15
-
16
- module ClassMethods
17
- def except_for(*ids)
18
- scoped.where("#{quoted_table_name}.id NOT IN (?)", ids)
19
- end
20
-
21
- def since(time)
22
- scoped.where("#{quoted_table_name}.created_at > ?", time)
23
- end
24
-
25
- alias created_since since
26
-
27
- def before(time)
28
- scoped.where("#{quoted_table_name}.created_at < ?", time)
29
- end
30
-
31
- def updated_since(time)
32
- scoped.where("#{quoted_table_name}.updated_at > ?", time)
33
- end
34
-
35
- def between(start_at, end_at)
36
- scoped.where("#{quoted_table_name}.created_at BETWEEN ? AND ", start_at, end_at)
37
- end
38
-
39
- def latest
40
- scoped.order("#{quoted_table_name}.id ASC").last
41
- end
42
-
43
- # shim for backwards compatibility with Rails 3
44
- def scoped
45
- where(nil)
46
- end if ::Rails::VERSION::MAJOR > 3
47
- end
48
- end
49
- end
2
+ module Ducks
3
+ module ActiveRecord
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ def associations?
9
+ associations.present?
10
+ end
11
+
12
+ def associations
13
+ results = []
14
+ refls = send respond_to?(:reflections) ? :reflections : :_reflections
15
+ refls.each do |key, reflection|
16
+ begin
17
+ if reflection.macro.to_s =~ /many/ ? public_send(key).exists? : public_send(key).present?
18
+ results << key
19
+ end
20
+ rescue
21
+ nil
22
+ end
23
+ end
24
+ results
25
+ end
26
+
27
+ module ClassMethods
28
+ def except_for(*ids)
29
+ scoped.where("#{quoted_table_name}.#{primary_key} NOT IN (?)", ids)
30
+ end
31
+
32
+ def since(time)
33
+ scoped.where("#{quoted_table_name}.created_at > ?", time)
34
+ end
35
+
36
+ alias created_since since
37
+
38
+ def before(time)
39
+ scoped.where("#{quoted_table_name}.created_at < ?", time)
40
+ end
41
+
42
+ def updated_since(time)
43
+ scoped.where("#{quoted_table_name}.updated_at > ?", time)
44
+ end
45
+
46
+ def between(start_at, end_at)
47
+ scoped.where("#{quoted_table_name}.created_at BETWEEN ? AND ", start_at, end_at)
48
+ end
49
+
50
+ # shim for backwards compatibility with Rails 3
51
+ def scoped
52
+ where(nil)
53
+ end if ::Rails::VERSION::MAJOR > 3
54
+ end
55
+ end
56
+ end
50
57
  end
@@ -41,7 +41,7 @@ module DuckPuncher
41
41
 
42
42
  def to_s
43
43
  if lines.any?
44
- lines.join.gsub /^\s{#{find_indent_size(lines.first)}}/, ''
44
+ lines.join.gsub(/^\s{#{find_indent_size(lines.first)}}/, '')
45
45
  else
46
46
  ''
47
47
  end
@@ -5,10 +5,17 @@ module DuckPuncher
5
5
  Marshal.load Marshal.dump self
6
6
  end unless defined? clone!
7
7
 
8
- def require!(file_or_gem, version = '')
8
+ def require!(file_or_gem, version = '', patience: 1)
9
9
  if DuckPuncher::GemInstaller.new.perform(file_or_gem, version)
10
- require file_or_gem.tr('-', '/')
10
+ if require file_or_gem.tr('-', '/')
11
+ true
12
+ elsif patience > 0
13
+ sleep 0.005
14
+ require!(file_or_gem, version, patience: patience - 1)
15
+ end
11
16
  end
17
+ rescue ::LoadError
18
+ require!(file_or_gem, version, patience: patience - 1) unless patience.zero?
12
19
  end
13
20
 
14
21
  # @description Returns a new decorated version of ourself with the punches mixed in (adds ancestors decorators)
@@ -32,15 +39,17 @@ module DuckPuncher
32
39
  self
33
40
  end
34
41
 
35
- def track
42
+ def track!(patience: 1)
36
43
  begin
37
- require 'object_tracker' || raise(LoadError)
38
- rescue LoadError
44
+ require 'object_tracker' || raise(::LoadError)
45
+ rescue ::LoadError
39
46
  DuckPuncher.(Object, only: :require!) unless respond_to? :require!
40
47
  require! 'object_tracker'
41
48
  end
42
- extend ::ObjectTracker
43
- track_all!
49
+ ::ObjectTracker.(self)
50
+ rescue ::Exception
51
+ sleep 0.005
52
+ track!(patience: patience - 1) unless patience.zero?
44
53
  end
45
54
  end
46
55
  end
@@ -19,7 +19,7 @@ class DuckPuncher::GemInstaller
19
19
  def perform(*args)
20
20
  require 'rubygems/dependency_installer'
21
21
  installer = Gem::DependencyInstaller.new(install_dir: Bundler.bundle_path.to_s, bin_dir: RbConfig::CONFIG['bindir'])
22
- installer.install *args.reject(&:empty?)
22
+ installer.install(*args.reject(&:empty?))
23
23
  installer.installed_gems.each do |gem|
24
24
  full_load_path = Bundler.bundle_path.join('gems', "#{gem.name}-#{gem.version}", "lib")
25
25
  next if $LOAD_PATH.include?(full_load_path.to_s)
@@ -7,7 +7,7 @@ module DuckPuncher
7
7
  end
8
8
 
9
9
  def self.write(file_name, key, load_path)
10
- FileUtils.mkdir(dir_name) unless File.exists?(dir_name)
10
+ FileUtils.mkdir(dir_name) unless File.exist?(dir_name)
11
11
  data = read(file_name)
12
12
  key = key.to_sym
13
13
  data[key] ||= {}
@@ -18,7 +18,7 @@ module DuckPuncher
18
18
  end
19
19
 
20
20
  def self.read(file_name)
21
- if File.exists?(dir_name.join file_name)
21
+ if File.exist?(dir_name.join file_name)
22
22
  JSON.parse File.read(dir_name.join file_name), symbolize_names: true
23
23
  else
24
24
  {}
@@ -1,25 +1,37 @@
1
1
  module DuckPuncher
2
2
  # @note When updating this file please update comment regarding this module in duck_puncher.rb
3
3
  module Registration
4
- def register(target, *mods)
4
+ # Register an extension with a target class
5
+ # When given a block, the block is used to create an anonymous module
6
+ # @param target [Class,Module,Object] constant or instance to extend
7
+ # @param mods [Array<Module>] modules to extend or mix into the target. The last argument can be a hash of options to customize the extension
8
+ # @option :only [Symbol, Array<Symbol>] list of methods to extend onto the target (the module must have these defined)
9
+ # @option :method [Symbol,String] the method used to apply the module, e.g. :extend (:include)
10
+ # @option :before [Proc] A hook that is called with the target class before #punch
11
+ # @option :after [Proc] A hook that is called with the target class after #punch
12
+ def register(target, *mods, &block)
5
13
  options = mods.last.is_a?(Hash) ? mods.pop : {}
14
+ mods << Module.new(&block) if block
6
15
  target = DuckPuncher.lookup_constant target
7
16
  Ducks.list[target] = Set.new [] unless Ducks.list.key?(target)
8
17
  mods = Array(mods).each do |mod|
9
- duck = UniqueDuck.new Duck.new target, mod, options
18
+ duck = UniqueDuck.new Duck.new(target, mod, options)
10
19
  Ducks.list[target] << duck
11
20
  end
12
21
  [target, *mods]
13
22
  end
14
23
 
15
- def register!(*args)
16
- register *args
17
- call args.first
24
+ # Register an extension and then immediately activate it
25
+ # See #register for accepted arguments
26
+ def register!(*args, &block)
27
+ register(*args, &block)
28
+ call(args.first)
18
29
  end
19
30
 
20
- def deregister(*classes)
21
- classes.each &Ducks.list.method(:delete)
22
- classes.each &decorators.method(:delete)
31
+ # Remove extensions for a given class or list of classes
32
+ def deregister(*targets)
33
+ targets.each(&Ducks.list.method(:delete))
34
+ targets.each(&decorators.method(:delete))
23
35
  end
24
36
  end
25
37
  end
@@ -1,3 +1,3 @@
1
1
  module DuckPuncher
2
- VERSION = '4.4.2'.freeze
2
+ VERSION = '5.0.1'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: duck_puncher
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.4.2
4
+ version: 5.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Buckley
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-11 00:00:00.000000000 Z
11
+ date: 2021-07-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: usable
@@ -28,14 +28,14 @@ dependencies:
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.3'
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: '1.3'
41
41
  - !ruby/object:Gem::Dependency
@@ -83,21 +83,10 @@ dependencies:
83
83
  description: Administer precision punches
84
84
  email:
85
85
  - arebuckley@gmail.com
86
- executables:
87
- - console
86
+ executables: []
88
87
  extensions: []
89
88
  extra_rdoc_files: []
90
89
  files:
91
- - ".gitignore"
92
- - ".ruby-gemset"
93
- - ".ruby-version"
94
- - ".travis.yml"
95
- - CHANGELOG.md
96
- - Gemfile
97
- - LICENSE.txt
98
- - README.md
99
- - Rakefile
100
- - bin/console
101
90
  - duck_puncher.gemspec
102
91
  - lib/duck_puncher.rb
103
92
  - lib/duck_puncher/ancestral_hash.rb
@@ -119,23 +108,11 @@ files:
119
108
  - lib/duck_puncher/unique_duck.rb
120
109
  - lib/duck_puncher/utilities.rb
121
110
  - lib/duck_puncher/version.rb
122
- - test/fixtures/test_classes.rb
123
- - test/fixtures/wut.rb
124
- - test/lib/duck_puncher/duck_test.rb
125
- - test/lib/duck_puncher/enumerable_test.rb
126
- - test/lib/duck_puncher/hash_test.rb
127
- - test/lib/duck_puncher/method_test.rb
128
- - test/lib/duck_puncher/module_test.rb
129
- - test/lib/duck_puncher/numeric_test.rb
130
- - test/lib/duck_puncher/object_test.rb
131
- - test/lib/duck_puncher/string_test.rb
132
- - test/lib/duck_puncher_test.rb
133
- - test/test_helper.rb
134
111
  homepage: https://github.com/ridiculous/duck_puncher
135
112
  licenses:
136
113
  - MIT
137
114
  metadata: {}
138
- post_install_message:
115
+ post_install_message:
139
116
  rdoc_options: []
140
117
  require_paths:
141
118
  - lib
@@ -150,21 +127,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
127
  - !ruby/object:Gem::Version
151
128
  version: '0'
152
129
  requirements: []
153
- rubyforge_project:
154
- rubygems_version: 2.5.1
155
- signing_key:
130
+ rubygems_version: 3.2.11
131
+ signing_key:
156
132
  specification_version: 4
157
133
  summary: Administer precision extensions (a.k.a "punches") to your favorite Ruby classes
158
- test_files:
159
- - test/fixtures/test_classes.rb
160
- - test/fixtures/wut.rb
161
- - test/lib/duck_puncher/duck_test.rb
162
- - test/lib/duck_puncher/enumerable_test.rb
163
- - test/lib/duck_puncher/hash_test.rb
164
- - test/lib/duck_puncher/method_test.rb
165
- - test/lib/duck_puncher/module_test.rb
166
- - test/lib/duck_puncher/numeric_test.rb
167
- - test/lib/duck_puncher/object_test.rb
168
- - test/lib/duck_puncher/string_test.rb
169
- - test/lib/duck_puncher_test.rb
170
- - test/test_helper.rb
134
+ test_files: []
data/.gitignore DELETED
@@ -1,19 +0,0 @@
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
- .duck_puncher/
19
- .byebug_history