rubyexts 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.
Files changed (51) hide show
  1. data/CHANGELOG +2 -0
  2. data/LICENSE +20 -0
  3. data/README.textile +0 -0
  4. data/Rakefile +79 -0
  5. data/TODO.txt +6 -0
  6. data/lib/rubyexts.rb +102 -0
  7. data/lib/rubyexts/array.rb +20 -0
  8. data/lib/rubyexts/attribute.rb +151 -0
  9. data/lib/rubyexts/capture_io.rb +32 -0
  10. data/lib/rubyexts/class.rb +177 -0
  11. data/lib/rubyexts/colored_string.rb +103 -0
  12. data/lib/rubyexts/enumerable.rb +30 -0
  13. data/lib/rubyexts/file.rb +84 -0
  14. data/lib/rubyexts/hash.rb +180 -0
  15. data/lib/rubyexts/kernel.rb +91 -0
  16. data/lib/rubyexts/module.rb +53 -0
  17. data/lib/rubyexts/object.rb +56 -0
  18. data/lib/rubyexts/object_space.rb +16 -0
  19. data/lib/rubyexts/os.rb +89 -0
  20. data/lib/rubyexts/platform.rb +27 -0
  21. data/lib/rubyexts/random.rb +25 -0
  22. data/lib/rubyexts/string.rb +92 -0
  23. data/lib/rubyexts/time.rb +15 -0
  24. data/lib/rubyexts/time_dsl.rb +62 -0
  25. data/lib/rubyexts/try_dup.rb +43 -0
  26. data/lib/rubyexts/unique_array.rb +16 -0
  27. data/rubyexts.gemspec +36 -0
  28. data/script/spec +12 -0
  29. data/spec/rubyexts/array_spec.rb +19 -0
  30. data/spec/rubyexts/attribute_spec.rb +37 -0
  31. data/spec/rubyexts/class_spec.rb +1 -0
  32. data/spec/rubyexts/cli_spec.rb +0 -0
  33. data/spec/rubyexts/colored_string_spec.rb +9 -0
  34. data/spec/rubyexts/enumerable_spec.rb +52 -0
  35. data/spec/rubyexts/file_spec.rb +78 -0
  36. data/spec/rubyexts/hash_spec.rb +91 -0
  37. data/spec/rubyexts/kernel_spec.rb +9 -0
  38. data/spec/rubyexts/module_spec.rb +0 -0
  39. data/spec/rubyexts/object_space_spec.rb +17 -0
  40. data/spec/rubyexts/object_spec.rb +57 -0
  41. data/spec/rubyexts/os_spec.rb +121 -0
  42. data/spec/rubyexts/platform_spec.rb +0 -0
  43. data/spec/rubyexts/random_spec.rb +31 -0
  44. data/spec/rubyexts/string_spec.rb +23 -0
  45. data/spec/rubyexts/time_dsl_spec.rb +88 -0
  46. data/spec/rubyexts/time_spec.rb +11 -0
  47. data/spec/rubyexts/unique_array_spec.rb +0 -0
  48. data/spec/rubyexts_spec.rb +182 -0
  49. data/spec/spec.opts +5 -0
  50. data/spec/spec_helper.rb +16 -0
  51. metadata +104 -0
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ # Extends the module object with module and instance accessors for class attributes,
4
+ # just like the native attr* accessors for instance attributes.
5
+ #
6
+ # module AppConfiguration
7
+ # mattr_accessor :google_api_key
8
+ # self.google_api_key = "123456789"
9
+ #
10
+ # mattr_accessor :paypal_url
11
+ # self.paypal_url = "www.sandbox.paypal.com"
12
+ # end
13
+ #
14
+ # AppConfiguration.google_api_key = "overriding the api key!"
15
+ class Module
16
+ def mattr_reader(*syms)
17
+ syms.each do |sym|
18
+ next if sym.is_a?(Hash)
19
+ class_eval(<<-EOS, __FILE__, __LINE__)
20
+ unless defined? @@#{sym}
21
+ @@#{sym} = nil
22
+ end
23
+
24
+ def self.#{sym}
25
+ @@#{sym}
26
+ end
27
+
28
+ def #{sym}
29
+ @@#{sym}
30
+ end
31
+ EOS
32
+ end
33
+ end
34
+
35
+ def mattr_writer(*syms)
36
+ syms.each do |sym|
37
+ class_eval(<<-EOS, __FILE__, __LINE__)
38
+ unless defined? @@#{sym}
39
+ @@#{sym} = nil
40
+ end
41
+
42
+ def self.#{sym}=(obj)
43
+ @@#{sym} = obj
44
+ end
45
+ EOS
46
+ end
47
+ end
48
+
49
+ def mattr_accessor(*syms)
50
+ mattr_reader(*syms)
51
+ mattr_writer(*syms)
52
+ end
53
+ end
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+
3
+ class Object
4
+ # *Unlike* that method however, a +NoMethodError+ exception will *not* be raised
5
+ # and +nil+ will be returned instead, if the receiving object is a +nil+ object or NilClass.
6
+ #
7
+ # Invokes the method identified by the symbol +method+, passing it any arguments
8
+ # and/or the block specified, just like the regular Ruby <tt>Object#send</tt> does.
9
+ #
10
+ # @author Botanicus
11
+ # @since 0.0.3
12
+ # @return [Object, nil] Return value of object.send(method) if object respond to method or nil
13
+ # @param [Symbol] Method which will be called on object if object respond to this method
14
+ # @param [Object, optional] Arguments for +method+ argument
15
+ # @yield [block, optional] Block for +method+ argument
16
+ # @example
17
+ # @post.try(:name) # instead @post && @post.name
18
+ # eBook.try(:find, 1)
19
+ # @post.try(:collect) { |p| p.name }
20
+ def try(method, *args, &block)
21
+ self.send(method, *args, &block) if self.respond_to?(method)
22
+ end
23
+
24
+ # The opposite of <tt>#nil?</tt>.
25
+ #
26
+ # @author Botanicus
27
+ # @since 0.0.3
28
+ # @return [true, false] True if self is nil, false otherwise
29
+ def not_nil?
30
+ not self.nil?
31
+ end
32
+
33
+ # Defines a instance method on class of the object.
34
+ #
35
+ # @author Botanicus
36
+ # @since 0.0.3
37
+ # @param [Symbol] Method name
38
+ # @param [Method, Proc, optional] +Method+ or +Proc+ which will be used as body of the method
39
+ # @yield [block] Block which will be used as body of the method
40
+ # @return [Object] First (and only) item of the array
41
+ # @see <tt>Module#define_singleton_method</tt> for define method on singleton class
42
+ # @example
43
+ # class Experiment
44
+ # def method_generator
45
+ # define_instance_method(:new_method) do |arg|
46
+ # puts "Method :new_method called with #{arg}"
47
+ # end
48
+ # end
49
+ # end
50
+ # Experiment.new.methods.include?(:new_method) # => false
51
+ # Experiment.new.method_generator
52
+ # Experiment.new.methods.include?(:new_method) # => true
53
+ def define_instance_method(*args, &block)
54
+ self.class.send(:define_method, *args, &block)
55
+ end
56
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ module ObjectSpace
4
+ # Returns all classes existing in runtime
5
+ #
6
+ # @author Botanicus
7
+ # @since 0.0.3
8
+ # @return [Array<Class>] List of all classes loaded into runtime
9
+ def self.classes
10
+ Array.new.tap do |objects|
11
+ self.each_object(Class) do |object|
12
+ objects << object
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,89 @@
1
+ # encoding: utf-8
2
+
3
+ class OS
4
+ # Takes ENV or another hash-like object and convert it into OS instance
5
+ #
6
+ # @author Botanicus
7
+ # @since 0.0.3
8
+ # @param [ENV, Hash] ENV or another hash-like object
9
+ # @return [OS] Instance of OS
10
+ # @example
11
+ # OS.parse
12
+ # OS.parse("HOME" => "/Users/botanicus")
13
+ def self.parse(original_env = ENV)
14
+ input = original_env.select { |key, value| key.match(/^[a-zA-Z][a-zA-Z_]*$/) }
15
+ result = Hash.new
16
+ input.each { |key, value| result[key.downcase.to_sym] = value }
17
+ self.new(result, original_env)
18
+ end
19
+
20
+ attr_reader :env, :original_env
21
+ def initialize(env, original_env = env)
22
+ @env, @original_env = env, original_env
23
+ self.keys.each do |key|
24
+ if key.match(/(path|lib)$/)
25
+ # OS.path
26
+ # => ["/bin", "/usr/bin", "/sbin", "/usr/sbin"]
27
+ define_singleton_method(key) do
28
+ @env[key].split(":").uniq.sort
29
+ end
30
+ elsif @env[key].match(/^\d+$/)
31
+ define_singleton_method(key) { @env[key].to_i }
32
+ elsif @env[key].empty?
33
+ define_singleton_method(key) { nil }
34
+ else
35
+ # OS.home
36
+ # => "/Users/botanicus"
37
+ define_singleton_method(key) do
38
+ case value = @env[key]
39
+ when /^\d+$/ then value.to_i
40
+ when /^\d+\.\d+$/ then value.to_f
41
+ when /^true$/i then true
42
+ when /^false$/i then false
43
+ when /^$/ then nil
44
+ else value
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ # Get value for given key or nil
52
+ #
53
+ # @author Botanicus
54
+ # @since 0.0.3
55
+ # @param [Symbol] Key
56
+ # @return [OS] Instance of OS
57
+ # @example
58
+ # os[:home]
59
+ def [](key)
60
+ self.send(key) if self.keys.include?(key.to_sym)
61
+ end
62
+
63
+ def ==(other)
64
+ same_keys = self.keys == other.keys
65
+ same_values = self.keys.all? { |key| self[key] == other[key] }
66
+ same_keys && same_values
67
+ end
68
+
69
+ def keys
70
+ @env.keys.sort
71
+ end
72
+
73
+ def inspect
74
+ string = "#<OS keys=[%s]>"
75
+ format = lambda { |key| "#{key}=#{self.send(key).inspect}" }
76
+ inner = self.keys.sort.map(&format).join(", ")
77
+ string % inner
78
+ end
79
+
80
+ # TODO
81
+ def root?
82
+ self.uid.eql?(0)
83
+ end
84
+
85
+ private
86
+ def method_missing(name, *args, &block)
87
+ super(name, *args, &block) unless args.empty? && block.nil?
88
+ end
89
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+
3
+ module RubyExts
4
+ class Platform
5
+ class << self
6
+ def match?(platform)
7
+ !! RUBY_PLATFORM.match(/#{platform}/i)
8
+ end
9
+
10
+ def windows?
11
+ self.match?("mswin|mingw")
12
+ end
13
+
14
+ def linux?
15
+ self.match?("linux")
16
+ end
17
+
18
+ def osx?
19
+ self.match?("-darwin")
20
+ end
21
+
22
+ def unix?
23
+ self.linux? or self.osx?
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ class Array
4
+ # Returns random item from the array
5
+ #
6
+ # @author Botanicus
7
+ # @since 0.0.2
8
+ # @return [Object] Random item from array
9
+ def rand
10
+ self[Kernel.rand(length)]
11
+ end
12
+ alias_method :random, :rand
13
+ end
14
+
15
+ class Range
16
+ # Returns random item from the array
17
+ #
18
+ # @author Botanicus
19
+ # @since 0.0.2
20
+ # @return [Object] Random item from range
21
+ def rand
22
+ self.min + Kernel.rand(self.max)
23
+ end
24
+ alias_method :random, :rand
25
+ end
@@ -0,0 +1,92 @@
1
+ # encoding: utf-8
2
+
3
+ class String
4
+ # Transform self into titlecased string.
5
+ #
6
+ # @author Botanicus
7
+ # @since 0.0.3
8
+ # @return [String] Titlecased string
9
+ # @example
10
+ # "hello world!".titlecase # => "Hello World!"
11
+ def titlecase
12
+ self.gsub(/\b./) { $&.upcase }
13
+ end
14
+
15
+ # Transform self to +ColoredString+
16
+ # @since 0.0.1
17
+ # @example
18
+ # "message".colorize.red.bold
19
+ # @param [type] name explanation
20
+ # @return [String] Transfrom self to +ColoredString+
21
+ def colorize
22
+ require_relative "colored_string"
23
+ ColoredString.new(self)
24
+ end
25
+
26
+ def remove(pattern)
27
+ self.gsub(pattern, "")
28
+ end
29
+
30
+ def remove!(pattern)
31
+ self.gsub!(pattern, "")
32
+ end
33
+
34
+ ##
35
+ # Convert to snake case.
36
+ #
37
+ # "FooBar".snake_case #=> "foo_bar"
38
+ # "HeadlineCNNNews".snake_case #=> "headline_cnn_news"
39
+ # "CNN".snake_case #=> "cnn"
40
+ #
41
+ # @return [String] Receiver converted to snake case.
42
+ #
43
+ # @api public
44
+ def snake_case
45
+ return self.downcase if self =~ /^[A-Z]+$/
46
+ self.gsub(/([A-Z]+)(?=[A-Z][a-z]?)|\B[A-Z]/, '_\&') =~ /_*(.*)/
47
+ return $+.downcase
48
+ end
49
+
50
+ ##
51
+ # Convert to camel case.
52
+ #
53
+ # "foo_bar".camel_case #=> "FooBar"
54
+ #
55
+ # @return [String] Receiver converted to camel case.
56
+ #
57
+ # @api public
58
+ def camel_case
59
+ return self if self !~ /_/ && self =~ /[A-Z]+.*/
60
+ split('_').map{|e| e.capitalize}.join
61
+ end
62
+
63
+ ##
64
+ # Convert a path string to a constant name.
65
+ #
66
+ # "merb/core_ext/string".to_const_string #=> "Merb::CoreExt::String"
67
+ #
68
+ # @return [String] Receiver converted to a constant name.
69
+ #
70
+ # @api public
71
+ def to_const_string
72
+ gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
73
+ end
74
+
75
+ ##
76
+ # Convert a constant name to a path, assuming a conventional structure.
77
+ #
78
+ # "FooBar::Baz".to_const_path # => "foo_bar/baz"
79
+ #
80
+ # @return [String] Path to the file containing the constant named by receiver
81
+ # (constantized string), assuming a conventional structure.
82
+ #
83
+ # @api public
84
+ def to_const_path
85
+ snake_case.gsub(/::/, "/")
86
+ end
87
+
88
+ # For Rack
89
+ # @since 0.0.2
90
+ # @todo Is it still required?
91
+ alias_method :each, :each_line
92
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ class Time
4
+ # How long it takes to run the block in seconds
5
+ #
6
+ # @author Botanicus
7
+ # @since 0.0.3
8
+ # @return [Float] How long it takes to run the block in seconds
9
+ # @example
10
+ # Time.timer { sleep 2 } # => 2.030802
11
+ def self.timer(&block)
12
+ start = Time.now.tap { block.call }
13
+ return Time.now - start
14
+ end
15
+ end
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+
3
+ # stolen from merb-helpers
4
+
5
+ # Provides a a simple way of calling time units and to see the elapsed time between 2 moments
6
+ # @example
7
+ # 142.minutes => returns a value in seconds
8
+ # 7.days => returns a value in seconds
9
+ # 1.week => returns a value in seconds
10
+ # 2.weeks.ago => returns a date
11
+ # 1.year.since(time) => returns a date
12
+ # 5.months.since(2.weeks.from_now) => returns a date
13
+ module TimeDSL
14
+ def second
15
+ self * 1
16
+ end
17
+ alias_method :seconds, :second
18
+
19
+ def minute
20
+ self * 60
21
+ end
22
+ alias_method :minutes, :minute
23
+
24
+ def hour
25
+ self * 3600
26
+ end
27
+ alias_method :hours, :hour
28
+
29
+ def day
30
+ self * 86400
31
+ end
32
+ alias_method :days, :day
33
+
34
+ def week
35
+ self * 604800
36
+ end
37
+ alias_method :weeks, :week
38
+
39
+ def month
40
+ self * 2592000
41
+ end
42
+ alias_method :months, :month
43
+
44
+ def year
45
+ self * 31471200
46
+ end
47
+ alias_method :years, :year
48
+
49
+ # Reads best without arguments: 10.minutes.ago
50
+ def ago(time = ::Time.now)
51
+ time - self
52
+ end
53
+ alias :until :ago
54
+
55
+ # Reads best with argument: 10.minutes.since(time)
56
+ def since(time = ::Time.now)
57
+ time + self
58
+ end
59
+ alias :from_now :since
60
+ end
61
+
62
+ Numeric.send :include, TimeDSL