rubyexts 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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