duck_puncher 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ee22023f5904a77f13fdc09ac72eefa9170938ea
4
- data.tar.gz: 28fb5cc8000d7de6240b6cf6c41e476861c4e255
3
+ metadata.gz: d30be8964065fb57d3de53e4e23b2deaf8ceb277
4
+ data.tar.gz: f2bc471c1a31a1f438680f21440b86d489092cd1
5
5
  SHA512:
6
- metadata.gz: fb0141394a399c457e4650f607ed66c7c924aa9c7e15030faafd1c20a18d812b620bc13864bcda8904720aa1218f65d915fdf8601af4e6dc4c412ebb722a0523
7
- data.tar.gz: 9f86ea17b513e5e3e0e4da59c6665c398e6f26b8229b9d58f5f012578147577ad7755ef1775626f75ab69063159abf45b00acb03c323ff583905c52c2fbe98ec
6
+ metadata.gz: e117be77a8e6a2a80f0ba415315039fa727ba1495e52bfa9b83cd7b5d631b92ebce331eaac51f6b7fb2d5c76a00e2f88f19892f4f84039686fab277976a40588
7
+ data.tar.gz: 64a2e78858356beacb9f30ea6cd6955046c8f90fc596fd0d15c64cbe2e121423e85b9ffe384e08826655f45eddc74bae824a6c401877e65ebf62c44908adc851
data/README.md CHANGED
@@ -2,33 +2,42 @@
2
2
 
3
3
  These are the ducks I can punch:
4
4
 
5
- Array#m => `[].m(:to_s)` alias for `[].map(&:to_s)`
6
- Array#mm => `[].mm(:sub, /[aeiou]/, '*')` alias for `[].map { |x| x.sub(/[aeiou]/, '*') }`
7
- Array#get => `[].methods.get('ty?')` searches the array for a string matching the 'ty?' (e.g. [:empty?])
8
- Hash#seek => `{a: 1, b: {c: 2}}.seek(:b, :c)` returns the value of nested hash keys (e.g. 2)
9
- Numeric#to_currency => `25.245.to_currency` formats a number in currency (e.g. '25.25' or '1.00')
10
- Numeric#to_duration => `10_000.to_duration` turns a number into duration (e.g. '2 h 46 min')
11
- Numeric#to_time_ago => `10_000.to_time_ago` turns a number into time ago (e.g. '2 hours ago')
12
- Numeric#to_rad => `10.15.to_rad` returns 0.17715091907742445
13
- String#pluralize => `'hour'.pluralize(2)` turns "hour" into "hours"
14
- Object#clone! => `Object.new.clone!` makes a deep clone of the object (using Marshal)
15
- Object#require! => Downloads and activates a gem for the current and subsequent consoles. For example:
16
- >> `require 'pry'`
17
- LoadError: cannot load such file -- pry
18
- from (irb):1:in `require'
19
- from (irb):1
20
- from bin/console:10:in `<main>'
21
- >> require! 'pry'
22
- Fetching: method_source-0.8.2.gem (100%)
23
- Fetching: slop-3.6.0.gem (100%)
24
- Fetching: coderay-1.1.0.gem (100%)
25
- Fetching: pry-0.10.3.gem (100%)
26
- => true
27
- >> Pry.start
28
- [1] pry(main)>
5
+ Array#m => `[].m(:to_s)` => `[].map(&:to_s)`
6
+ Array#mm => `[].mm(:sub, /[aeiou]/, '*')` => `[].map { |x| x.sub(/[aeiou]/, '*') }`
7
+ Array#get => `[].methods.get('ty?')` => [:empty?]
8
+ Hash#seek => `{a: 1, b: {c: 2}}.seek(:b, :c)` => 2
9
+ Numeric#to_currency => `25.245.to_currency` => 25.25
10
+ Numeric#to_duration => `10_000.to_duration` => '2 h 46 min'
11
+ Numeric#to_time_ago => `10_000.to_time_ago` => '2 hours ago'
12
+ Numeric#to_rad => `10.15.to_rad` => 0.17715091907742445
13
+ String#pluralize => `'hour'.pluralize(2)` => "hours"
14
+ String#underscore => `'DuckPuncher::JSONStorage'.underscore` => 'duck_puncher/json_storage'
15
+ Object#clone! => `Object.new.clone!` => a deep clone of the object (using Marshal.dump)
29
16
  Method#to_instruct => `Benchmark.method(:measure).to_instruct` returns the Ruby VM instruction sequence for the method
30
17
  Method#to_source => `Benchmark.method(:measure).to_source` returns the method definition as a string
18
+
19
+ I also provide an experimental punch that tries to download the required gem if it doesn't exist on your computer. The
20
+ method is called `require!` and works like this:
21
+
22
+ Downloads and activates a gem for the current and subsequent consoles. For example:
23
+
24
+ ```bash
25
+ >> `require 'pry'`
26
+ LoadError: cannot load such file -- pry
27
+ from (irb):1:in `require'
28
+ from (irb):1
29
+ from bin/console:10:in `<main>'
30
+ >> require! 'pry'
31
+ Fetching: method_source-0.8.2.gem (100%)
32
+ Fetching: slop-3.6.0.gem (100%)
33
+ Fetching: coderay-1.1.0.gem (100%)
34
+ Fetching: pry-0.10.3.gem (100%)
35
+ => true
36
+ >> Pry.start
37
+ [1] pry(main)>
38
+ ```
31
39
 
40
+ Try it out if your feeling frisky! However, I noticed it doesn't work well with bigger gems and those with native extensions.
32
41
 
33
42
  ## Install
34
43
 
data/bin/console CHANGED
@@ -5,6 +5,7 @@ require 'pp'
5
5
  require 'duck_puncher'
6
6
  require 'irb'
7
7
  require_relative '../test/fixtures/wut'
8
+
8
9
  DuckPuncher.punch_all!
9
10
 
10
11
  IRB.start
@@ -0,0 +1,30 @@
1
+ module DuckPuncher
2
+ class Duck
3
+ attr_accessor :name, :options
4
+
5
+ def initialize(name, options = {})
6
+ @name = name
7
+ @options = options
8
+ @punched = false
9
+ end
10
+
11
+ def load_path
12
+ "duck_puncher/ducks/#{name.to_s.downcase}"
13
+ end
14
+
15
+ def punch
16
+ return false if options[:if] && !options[:if].call
17
+ options[:before].call if options[:before]
18
+ const.send :include, DuckPuncher::Ducks.const_get(name)
19
+ @punched = true
20
+ end
21
+
22
+ def const
23
+ @const ||= (options[:class] || name).to_s.split('::').inject(Kernel) { |k, part| k.const_get part }
24
+ end
25
+
26
+ def punched?
27
+ @punched
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,48 @@
1
+ module DuckPuncher
2
+ module ActiveRecord
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ def associations?
8
+ associations.present?
9
+ end
10
+
11
+ def associations
12
+ reflections.select { |key, _| send(key).present? rescue nil }.keys
13
+ end
14
+
15
+ module ClassMethods
16
+ def except_for(*ids)
17
+ scoped.where("#{quoted_table_name}.id NOT IN (?)", ids)
18
+ end
19
+
20
+ def since(time)
21
+ scoped.where("#{quoted_table_name}.created_at > ?", time)
22
+ end
23
+
24
+ alias created_since since
25
+
26
+ def before(time)
27
+ scoped.where("#{quoted_table_name}.created_at < ?", time)
28
+ end
29
+
30
+ def updated_since(time)
31
+ scoped.where("#{quoted_table_name}.updated_at > ?", time)
32
+ end
33
+
34
+ def between(start_at, end_at)
35
+ scoped.where("#{quoted_table_name}.created_at BETWEEN ? AND ", start_at, end_at)
36
+ end
37
+
38
+ def latest
39
+ scoped.order("#{quoted_table_name}.id ASC").last
40
+ end
41
+
42
+ # shim for backwards compatibility with Rails 3
43
+ def scoped
44
+ where(nil)
45
+ end if Rails::VERSION::MAJOR != 3
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,18 @@
1
+ module DuckPuncher
2
+ module Ducks
3
+ module Array
4
+ def m(method_name)
5
+ map(&method_name)
6
+ end
7
+
8
+ def mm(method_name, *args)
9
+ map { |x| x.public_send(method_name, *args) }
10
+ end
11
+
12
+ def get(regex_or_str)
13
+ regex = regex_or_str.is_a?(Regexp) ? regex_or_str : Regexp.new(Regexp.escape(regex_or_str))
14
+ select { |x| x.to_s =~ regex }
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,25 @@
1
+ module DuckPuncher
2
+ module Ducks
3
+ module Hash
4
+ # http://coryodaniel.com/index.php/2009/12/30/ruby-getting-deeply-nested-values-from-a-hash-in-one-line-of-code/
5
+ def seek(*_keys_)
6
+ last_level = self
7
+ sought_value = nil
8
+
9
+ _keys_.each_with_index do |_key_, _idx_|
10
+ if last_level.is_a?(Hash) && last_level.has_key?(_key_)
11
+ if _idx_ + 1 == _keys_.length
12
+ sought_value = last_level[_key_]
13
+ else
14
+ last_level = last_level[_key_]
15
+ end
16
+ else
17
+ break
18
+ end
19
+ end
20
+
21
+ sought_value
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,56 @@
1
+ module DuckPuncher
2
+ module Ducks
3
+ module Method
4
+ def to_instruct
5
+ definition = Definition.new(self)
6
+ RubyVM::InstructionSequence.new(definition.lines.join).disasm if definition.lines.any?
7
+ end
8
+
9
+ def to_source
10
+ Definition.new(self).to_s
11
+ end
12
+
13
+ class Definition
14
+ def initialize(method_handle)
15
+ @file_path, @line_num = *method_handle.source_location
16
+ @line_num = @line_num.to_i
17
+ end
18
+
19
+ # @description finds the method's source code using the indent size of the file. This means we are
20
+ # restricted when it comes to parsing crappy formatted ruby files
21
+ def lines
22
+ return @lines if defined? @lines
23
+ return [] unless @file_path
24
+ @lines = []
25
+ File.open(@file_path) do |f|
26
+ found = false
27
+ i = 0
28
+ while line = f.gets and i += 1 and !found
29
+ next if i < @line_num
30
+ @lines << line
31
+ if @indent_size
32
+ found = @indent_size == find_indent_size(line)
33
+ else
34
+ @indent_size = find_indent_size(line)
35
+ found = line.end_with?("end\n")
36
+ end
37
+ end
38
+ end
39
+ @lines
40
+ end
41
+
42
+ def to_s
43
+ if lines.any?
44
+ lines.join.gsub /^\s{#{find_indent_size(lines.first)}}/, ''
45
+ else
46
+ ''
47
+ end
48
+ end
49
+
50
+ def find_indent_size(line)
51
+ line[/(\s*)/].size
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,51 @@
1
+ module DuckPuncher
2
+ module Ducks
3
+ module Numeric
4
+ def to_currency(prefix = '')
5
+ "#{prefix}%.2f" % self.round(2)
6
+ end
7
+
8
+ def to_duration(seconds = false)
9
+ secs = to_i
10
+ mins = secs / 60
11
+ hours = mins / 60
12
+ buffer = ''
13
+ if hours > 0
14
+ num_mins = mins % 60
15
+ buffer << "#{hours} h"
16
+ buffer << " #{num_mins} min" unless num_mins.zero?
17
+ elsif mins > 0
18
+ num_secs = secs % 60
19
+ buffer << "#{mins} min"
20
+ buffer << " #{num_secs} s" if seconds && num_secs.nonzero?
21
+ elsif seconds && secs >= 0
22
+ buffer << "#{secs} s"
23
+ end
24
+ buffer
25
+ end
26
+
27
+ # similar to Rails' #time_ago_in_words
28
+ def to_time_ago
29
+ secs = to_i
30
+ mins = secs / 60
31
+ hours = mins / 60
32
+ days = hours / 24
33
+ buffer = ''
34
+ if days > 0
35
+ buffer << "#{days} #{'day'.pluralize(days)}"
36
+ elsif hours > 0
37
+ buffer << "#{hours} #{'hour'.pluralize(hours)}"
38
+ elsif mins > 0
39
+ buffer << "#{mins} #{'minute'.pluralize(mins)}"
40
+ elsif secs >= 0
41
+ buffer << "less than a minute"
42
+ end
43
+ buffer << ' ago'
44
+ end
45
+
46
+ def to_rad
47
+ self / 180 * Math::PI
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,15 @@
1
+ module DuckPuncher
2
+ module Ducks
3
+ module Object
4
+ def clone!
5
+ Marshal.load Marshal.dump self
6
+ end unless defined? clone!
7
+
8
+ def require!(file_or_gem, version = '')
9
+ if DuckPuncher::GemInstaller.new.perform(file_or_gem, version)
10
+ require file_or_gem.tr('-', '/')
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ module DuckPuncher
2
+ module Ducks
3
+ module String
4
+ def pluralize(count)
5
+ "#{self}#{'s' if count != 1}"
6
+ end unless method_defined?(:pluralize)
7
+
8
+ def underscore
9
+ gsub(/\B([A-Z])([a-z_0-9])/, '_\1\2').gsub('::', '/').downcase
10
+ end unless method_defined?(:underscore)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ module DuckPuncher
2
+ module Ducks
3
+ class << self
4
+ def list
5
+ @list ||= [
6
+ Duck.new(:Array),
7
+ Duck.new(:Numeric),
8
+ Duck.new(:Hash),
9
+ Duck.new(:String),
10
+ Duck.new(:Object),
11
+ Duck.new(:Method, before: -> { DuckPuncher::GemInstaller.initialize! }),
12
+ Duck.new(:ActiveRecord, class: 'ActiveRecord::Base', if: -> { defined? ::ActiveRecord })
13
+ ]
14
+ end
15
+
16
+ def [](name)
17
+ list.find { |duck| duck.name == name.to_sym }
18
+ end
19
+ end
20
+
21
+ #
22
+ # Autoload our ducks
23
+ #
24
+
25
+ list.each do |duck|
26
+ autoload duck.name, duck.load_path
27
+ end
28
+ end
29
+ end
@@ -1,5 +1,3 @@
1
- require_relative 'json_storage'
2
-
3
1
  class DuckPuncher::GemInstaller
4
2
  def self.initialize!
5
3
  spec_data = DuckPuncher::JSONStorage.read('load_paths.json').values
@@ -19,7 +17,6 @@ class DuckPuncher::GemInstaller
19
17
  # @param [String] name of the gem
20
18
  # @param [String] version of the gem to install (e.g. '1.2.3')
21
19
  def perform(*args)
22
- require 'rubygems/dependency_installer'
23
20
  installer = Gem::DependencyInstaller.new(install_dir: Bundler.bundle_path.to_s, bin_dir: RbConfig::CONFIG['bindir'])
24
21
  installer.install *args.reject(&:empty?)
25
22
  installer.installed_gems.each do |gem|
@@ -1,3 +1,3 @@
1
1
  module DuckPuncher
2
- VERSION = '2.3.0'.freeze
2
+ VERSION = '2.4.0'.freeze
3
3
  end
data/lib/duck_puncher.rb CHANGED
@@ -1,24 +1,43 @@
1
1
  require 'pathname'
2
2
  require 'fileutils'
3
+ require 'logger'
3
4
  require 'duck_puncher/version'
4
5
 
5
6
  module DuckPuncher
6
- autoload :Array, 'duck_puncher/array'
7
- autoload :Numeric, 'duck_puncher/numeric'
8
- autoload :Hash, 'duck_puncher/hash'
9
- autoload :String, 'duck_puncher/string'
10
- autoload :Object, 'duck_puncher/object'
11
- autoload :Method, 'duck_puncher/method'
12
-
13
- if defined? ActiveRecord
14
- autoload :ActiveRecordExtensions, 'duck_puncher/active_record_extensions'
15
- end
7
+ autoload :JSONStorage, 'duck_puncher/json_storage'
8
+ autoload :GemInstaller, 'duck_puncher/gem_installer'
9
+ autoload :Duck, 'duck_puncher/duck'
10
+ autoload :Ducks, 'duck_puncher/ducks'
16
11
 
17
12
  def self.punch!(*names)
18
- names.each &method(:const_get)
13
+ names.each do |name|
14
+ if duck = Ducks[name]
15
+ if duck.punched?
16
+ log.info %Q(Already punched #{name})
17
+ else
18
+ log.warn %Q(Punching the #{name} ducky)
19
+ unless duck.punch
20
+ log.error %Q(Failed to punch #{name}!)
21
+ end
22
+ end
23
+ else
24
+ log.info %Q(Couldn't find "#{name}" in my list of Ducks! I know about: #{Ducks.list.map(&:name).map(&:to_s)})
25
+ end
26
+ end
27
+ nil
19
28
  end
20
29
 
21
30
  def self.punch_all!
22
- constants.each &method(:const_get)
31
+ log.warn 'Punching all ducks! Watch out!'
32
+ Ducks.list.each &:punch
33
+ end
34
+
35
+ class << self
36
+ attr_accessor :log
37
+ end
38
+
39
+ self.log = Logger.new(STDOUT).tap do |config|
40
+ config.level = Logger::INFO
41
+ config.formatter = proc { |*args| "#{args.first}: #{args.last.to_s}\n" }
23
42
  end
24
43
  end
@@ -6,4 +6,13 @@ class StringTest < MiniTest::Test
6
6
  assert_equal 'hour'.pluralize(0), 'hours'
7
7
  assert_equal 'hour'.pluralize(2), 'hours'
8
8
  end
9
+
10
+ def test_underscore
11
+ assert_equal 'MiniTest'.underscore, 'mini_test'
12
+ assert_equal 'MiniTestDoItToIt'.underscore, 'mini_test_do_it_to_it'
13
+ assert_equal 'MiniTest::Helper'.underscore, 'mini_test/helper'
14
+ assert_equal 'MiniTest::Helper::Expectations'.underscore, 'mini_test/helper/expectations'
15
+ assert_equal 'mini_test.rb', 'mini_test.rb'.underscore
16
+ assert_equal 'duck_puncher/json_storage', 'DuckPuncher::JSONStorage'.underscore
17
+ end
9
18
  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: 2.3.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Buckley
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-05 00:00:00.000000000 Z
11
+ date: 2016-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -97,15 +97,17 @@ files:
97
97
  - bin/console
98
98
  - duck_puncher.gemspec
99
99
  - lib/duck_puncher.rb
100
- - lib/duck_puncher/active_record_extensions.rb
101
- - lib/duck_puncher/array.rb
100
+ - lib/duck_puncher/duck.rb
101
+ - lib/duck_puncher/ducks.rb
102
+ - lib/duck_puncher/ducks/active_record.rb
103
+ - lib/duck_puncher/ducks/array.rb
104
+ - lib/duck_puncher/ducks/hash.rb
105
+ - lib/duck_puncher/ducks/method.rb
106
+ - lib/duck_puncher/ducks/numeric.rb
107
+ - lib/duck_puncher/ducks/object.rb
108
+ - lib/duck_puncher/ducks/string.rb
102
109
  - lib/duck_puncher/gem_installer.rb
103
- - lib/duck_puncher/hash.rb
104
110
  - lib/duck_puncher/json_storage.rb
105
- - lib/duck_puncher/method.rb
106
- - lib/duck_puncher/numeric.rb
107
- - lib/duck_puncher/object.rb
108
- - lib/duck_puncher/string.rb
109
111
  - lib/duck_puncher/version.rb
110
112
  - test/duck_puncher/array_test.rb
111
113
  - test/duck_puncher/hash_test.rb
@@ -1,48 +0,0 @@
1
- module ActiveRecordExtensions
2
- def self.included(base)
3
- base.extend(ClassMethods)
4
- end
5
-
6
- def associations?
7
- associations.present?
8
- end
9
-
10
- def associations
11
- reflections.select { |key, _| send(key).present? rescue nil }.keys
12
- end
13
-
14
- module ClassMethods
15
- def except_for(*ids)
16
- scoped.where("#{quoted_table_name}.id NOT IN (?)", ids)
17
- end
18
-
19
- def since(time)
20
- scoped.where("#{quoted_table_name}.created_at > ?", time)
21
- end
22
-
23
- alias created_since since
24
-
25
- def before(time)
26
- scoped.where("#{quoted_table_name}.created_at < ?", time)
27
- end
28
-
29
- def updated_since(time)
30
- scoped.where("#{quoted_table_name}.updated_at > ?", time)
31
- end
32
-
33
- def between(start_at, end_at)
34
- scoped.where("#{quoted_table_name}.created_at BETWEEN ? AND ", start_at, end_at)
35
- end
36
-
37
- def latest
38
- scoped.order("#{quoted_table_name}.id ASC").last
39
- end
40
-
41
- # shim for backwards compatibility with Rails 3
42
- def scoped
43
- where(nil)
44
- end if Rails::VERSION::MAJOR != 3
45
- end
46
- end
47
-
48
- ActiveRecord::Base.send(:include, ActiveRecordExtensions)
@@ -1,18 +0,0 @@
1
- module DuckPuncher
2
- module Array
3
- def m(method_name)
4
- map(&method_name)
5
- end
6
-
7
- def mm(method_name, *args)
8
- map { |x| x.public_send(method_name, *args) }
9
- end
10
-
11
- def get(regex_or_str)
12
- regex = regex_or_str.is_a?(Regexp) ? regex_or_str : Regexp.new(Regexp.escape(regex_or_str))
13
- select { |x| x.to_s =~ regex }
14
- end
15
- end
16
- end
17
-
18
- Array.send(:include, DuckPuncher::Array)
@@ -1,25 +0,0 @@
1
- module DuckPuncher
2
- module Hash
3
- # http://coryodaniel.com/index.php/2009/12/30/ruby-getting-deeply-nested-values-from-a-hash-in-one-line-of-code/
4
- def seek(*_keys_)
5
- last_level = self
6
- sought_value = nil
7
-
8
- _keys_.each_with_index do |_key_, _idx_|
9
- if last_level.is_a?(Hash) && last_level.has_key?(_key_)
10
- if _idx_ + 1 == _keys_.length
11
- sought_value = last_level[_key_]
12
- else
13
- last_level = last_level[_key_]
14
- end
15
- else
16
- break
17
- end
18
- end
19
-
20
- sought_value
21
- end
22
- end
23
- end
24
-
25
- Hash.send(:include, DuckPuncher::Hash)
@@ -1,56 +0,0 @@
1
- module DuckPuncher
2
- module Method
3
- def to_instruct
4
- definition = Definition.new(self)
5
- RubyVM::InstructionSequence.new(definition.lines.join).disasm if definition.lines.any?
6
- end
7
-
8
- def to_source
9
- Definition.new(self).to_s
10
- end
11
-
12
- class Definition
13
- def initialize(method_handle)
14
- @file_path, @line_num = *method_handle.source_location
15
- @line_num = @line_num.to_i
16
- end
17
-
18
- # @description finds the method's source code using the indent size of the file. This means we are
19
- # restricted when it comes to parsing crappy formatted ruby files
20
- def lines
21
- return @lines if defined? @lines
22
- return [] unless @file_path
23
- @lines = []
24
- File.open(@file_path) do |f|
25
- found = false
26
- i = 0
27
- while line = f.gets and i += 1 and !found
28
- next if i < @line_num
29
- @lines << line
30
- if @indent_size
31
- found = @indent_size == find_indent_size(line)
32
- else
33
- @indent_size = find_indent_size(line)
34
- found = line.end_with?("end\n")
35
- end
36
- end
37
- end
38
- @lines
39
- end
40
-
41
- def to_s
42
- if lines.any?
43
- lines.join.gsub /^\s{#{find_indent_size(lines.first)}}/, ''
44
- else
45
- ''
46
- end
47
- end
48
-
49
- def find_indent_size(line)
50
- line[/(\s*)/].size
51
- end
52
- end
53
- end
54
- end
55
-
56
- Method.send(:include, DuckPuncher::Method)
@@ -1,51 +0,0 @@
1
- module DuckPuncher
2
- module Numeric
3
- def to_currency(prefix = '')
4
- "#{prefix}%.2f" % self.round(2)
5
- end
6
-
7
- def to_duration(seconds = false)
8
- secs = to_i
9
- mins = secs / 60
10
- hours = mins / 60
11
- buffer = ''
12
- if hours > 0
13
- num_mins = mins % 60
14
- buffer << "#{hours} h"
15
- buffer << " #{num_mins} min" unless num_mins.zero?
16
- elsif mins > 0
17
- num_secs = secs % 60
18
- buffer << "#{mins} min"
19
- buffer << " #{num_secs} s" if seconds && num_secs.nonzero?
20
- elsif seconds && secs >= 0
21
- buffer << "#{secs} s"
22
- end
23
- buffer
24
- end
25
-
26
- # similar to Rails' #time_ago_in_words
27
- def to_time_ago
28
- secs = to_i
29
- mins = secs / 60
30
- hours = mins / 60
31
- days = hours / 24
32
- buffer = ''
33
- if days > 0
34
- buffer << "#{days} #{'day'.pluralize(days)}"
35
- elsif hours > 0
36
- buffer << "#{hours} #{'hour'.pluralize(hours)}"
37
- elsif mins > 0
38
- buffer << "#{mins} #{'minute'.pluralize(mins)}"
39
- elsif secs >= 0
40
- buffer << "less than a minute"
41
- end
42
- buffer << ' ago'
43
- end
44
-
45
- def to_rad
46
- self / 180 * Math::PI
47
- end
48
- end
49
- end
50
-
51
- Numeric.send(:include, DuckPuncher::Numeric)
@@ -1,19 +0,0 @@
1
- require_relative 'json_storage'
2
- require_relative 'gem_installer'
3
-
4
- module DuckPuncher
5
- module Object
6
- def clone!
7
- Marshal.load Marshal.dump self
8
- end unless defined? clone!
9
-
10
- def require!(file_or_gem, version = '')
11
- if DuckPuncher::GemInstaller.new.perform(file_or_gem, version)
12
- require file_or_gem.tr('-', '/')
13
- end
14
- end
15
- end
16
- end
17
-
18
- DuckPuncher::GemInstaller.initialize!
19
- Object.send(:include, DuckPuncher::Object)
@@ -1,9 +0,0 @@
1
- module DuckPuncher
2
- module String
3
- def pluralize(count)
4
- "#{self}#{'s' if count != 1}"
5
- end
6
- end
7
- end
8
-
9
- String.send(:include, DuckPuncher::String)