rubyexts 0.0.1 → 0.0.2
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.
- data/CHANGELOG +2 -0
- data/lib/rubyexts/attribute.rb +3 -1
- data/lib/rubyexts/kernel.rb +1 -3
- data/lib/rubyexts/logger.rb +101 -0
- data/lib/rubyexts/mixins/chainable.rb +68 -0
- data/lib/rubyexts/mixins/hookable.rb +32 -0
- data/lib/rubyexts/mixins/import.rb +89 -0
- data/lib/rubyexts/mixins/strategy.rb +28 -0
- data/lib/rubyexts/object.rb +0 -20
- data/lib/rubyexts/try.rb +23 -0
- data/lib/rubyexts.rb +1 -1
- data/rubyexts-0.0.1.gem +0 -0
- data/script/spec +2 -0
- metadata +8 -2
data/CHANGELOG
CHANGED
data/lib/rubyexts/attribute.rb
CHANGED
@@ -129,9 +129,11 @@ module AttributeMixin
|
|
129
129
|
# Post.new.updated?
|
130
130
|
# # => true
|
131
131
|
# @since 0.0.2
|
132
|
-
|
132
|
+
# questionable(:testing) { }
|
133
|
+
def questionable(name, default_value = nil, &block)
|
133
134
|
define_method("#{name}?") do
|
134
135
|
unless self.instance_variables.include?(name.to_sym)
|
136
|
+
default_value = block_given? ? self.instance_eval(&block) : default_value
|
135
137
|
self.instance_variable_set("@#{name}", default_value)
|
136
138
|
end
|
137
139
|
self.instance_variable_get("@#{name}")
|
data/lib/rubyexts/kernel.rb
CHANGED
@@ -32,9 +32,7 @@ module Kernel
|
|
32
32
|
require library
|
33
33
|
rescue LoadError => exception
|
34
34
|
message = "Gem #{gemname} isn't installed. Run sudo gem install #{gemname}. (#{exception.inspect})"
|
35
|
-
|
36
|
-
callable = defined?(Rango.logger) ? logger : method(:puts)
|
37
|
-
callable.call(message)
|
35
|
+
puts message
|
38
36
|
raise exception
|
39
37
|
end
|
40
38
|
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# TODO: documentation
|
4
|
+
# TODO: specs
|
5
|
+
require "logger"
|
6
|
+
require "rubyexts/string" # String#colorize
|
7
|
+
|
8
|
+
module RubyExts
|
9
|
+
class Logger < ::Logger
|
10
|
+
# @since 0.0.1
|
11
|
+
def initialize(output = STDERR)
|
12
|
+
super(output)
|
13
|
+
self.setup
|
14
|
+
end
|
15
|
+
|
16
|
+
# @since 0.0.1
|
17
|
+
def setup
|
18
|
+
self.level = ::Logger::DEBUG
|
19
|
+
self.datetime_format = "%H:%M:%S"
|
20
|
+
self.setup_format
|
21
|
+
end
|
22
|
+
|
23
|
+
# @since 0.0.1
|
24
|
+
def exception(exception)
|
25
|
+
self.error("#{exception.message} (#{exception.class})")
|
26
|
+
exception.backtrace.each do |line|
|
27
|
+
unless line.match(/thin|eventmachine/)
|
28
|
+
STDERR.puts("- #{line.colorize.cyan}")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Logger methods can takes more arguments and they returns array with arguments
|
34
|
+
# NOTE: why we dup args each time? Because we colorize messages, but if logger method
|
35
|
+
# is used for handling requests, we just need to send noncolored messages as response.
|
36
|
+
# @since 0.0.1
|
37
|
+
def debug(*args)
|
38
|
+
original = args.dup
|
39
|
+
args.map { |arg| super(arg) }
|
40
|
+
return original
|
41
|
+
end
|
42
|
+
|
43
|
+
# @since 0.0.1
|
44
|
+
def info(*args)
|
45
|
+
original = args.dup
|
46
|
+
args.map { |arg| super(arg) }
|
47
|
+
return original
|
48
|
+
end
|
49
|
+
|
50
|
+
# @since 0.0.1
|
51
|
+
def warn(*args)
|
52
|
+
original = args.dup
|
53
|
+
args.map { |arg| super(arg) }
|
54
|
+
return original
|
55
|
+
end
|
56
|
+
|
57
|
+
# @since 0.0.1
|
58
|
+
def error(*args)
|
59
|
+
original = args.dup
|
60
|
+
args.map { |arg| super(arg) }
|
61
|
+
return original
|
62
|
+
end
|
63
|
+
|
64
|
+
# @since 0.0.1
|
65
|
+
def fatal(*args)
|
66
|
+
original = args.dup
|
67
|
+
args.map { |arg| super(arg) }
|
68
|
+
return original
|
69
|
+
end
|
70
|
+
|
71
|
+
# Project.logger.inspect(@posts, item)
|
72
|
+
# Project.logger.inspect("@post" => @post)
|
73
|
+
# @since 0.0.1
|
74
|
+
def inspect(*args)
|
75
|
+
if args.first.is_a?(Hash) && args.length.eql?(1)
|
76
|
+
args.first.each do |name, value|
|
77
|
+
self.debug("#{name}: #{value.inspect}")
|
78
|
+
end
|
79
|
+
else
|
80
|
+
args = args.map { |arg| arg.inspect }
|
81
|
+
self.debug(*args)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# @since 0.0.1
|
86
|
+
def setup_format
|
87
|
+
self.formatter = lambda do |severity, datetime, progname, msg|
|
88
|
+
# logger.debug(object_to_inspect)
|
89
|
+
msg = msg.inspect unless msg.is_a?(String)
|
90
|
+
datetime = datetime.strftime("[%H:%M:%S]")
|
91
|
+
case severity
|
92
|
+
when "DEBUG" then "#{datetime} #{msg.colorize.yellow}\n"
|
93
|
+
when "INFO" then "#{datetime} #{msg.colorize.green}\n"
|
94
|
+
when "WARN" then "#{datetime} #{msg.colorize.yellow}\n"
|
95
|
+
when "ERROR" then "#{datetime} #{msg.colorize.red}\n"
|
96
|
+
when "FATAL" then "#{datetime} #{msg.colorize.red.bold}\n"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# from merb-core
|
4
|
+
module RubyExts
|
5
|
+
module Chainable
|
6
|
+
# Allows the definition of methods on a class that will be available via
|
7
|
+
# super.
|
8
|
+
#
|
9
|
+
# ==== Examples
|
10
|
+
# class Foo
|
11
|
+
# extend RubyExts::Chainable
|
12
|
+
# chainable do
|
13
|
+
# def hello
|
14
|
+
# "hello"
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# class Foo
|
20
|
+
# def hello
|
21
|
+
# super + " Merb!"
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# # Example with mixin:
|
26
|
+
# module TestMixin
|
27
|
+
# extend RubyExts::Chainable
|
28
|
+
# chainable do
|
29
|
+
# def test
|
30
|
+
# "from mixin!"
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# class Test
|
36
|
+
# include TestMixin
|
37
|
+
# def test
|
38
|
+
# "hello " + super
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# puts Test.new.test
|
43
|
+
#
|
44
|
+
#
|
45
|
+
# Foo.new.hello #=> "hello Merb!"
|
46
|
+
#
|
47
|
+
# ==== Parameters
|
48
|
+
# &block::
|
49
|
+
# a block containing method definitions that should be
|
50
|
+
# marked as chainable
|
51
|
+
#
|
52
|
+
# ==== Returns
|
53
|
+
# Module:: The anonymous module that was created
|
54
|
+
def chainable(method = nil, &block)
|
55
|
+
if method.nil? && block_given?
|
56
|
+
mixin = Module.new(&block)
|
57
|
+
include mixin
|
58
|
+
return mixin
|
59
|
+
elsif method && ! block_given?
|
60
|
+
# TODO
|
61
|
+
# def test
|
62
|
+
# # ...
|
63
|
+
# end
|
64
|
+
# chainable :test
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# class Test
|
4
|
+
# extend Rango::Hookable
|
5
|
+
# install_hook do |instance|
|
6
|
+
# p instance
|
7
|
+
# end
|
8
|
+
#
|
9
|
+
# def initialize
|
10
|
+
# p self
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# Test.new
|
15
|
+
|
16
|
+
module RubyExts
|
17
|
+
module Hookable
|
18
|
+
def new(*args)
|
19
|
+
instance = super(*args)
|
20
|
+
self.hooks.each { |hook| hook.call(instance) }
|
21
|
+
return instance
|
22
|
+
end
|
23
|
+
|
24
|
+
def hooks
|
25
|
+
@hooks ||= Array.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def install_hook(&block)
|
29
|
+
self.hooks.push(block)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# boot: after rango.rb
|
4
|
+
|
5
|
+
module RubyExts
|
6
|
+
# This mixin will be included also to project or your custom app main namespace
|
7
|
+
module ImportMixin
|
8
|
+
# class Project
|
9
|
+
# extend Rango::ImportMixin
|
10
|
+
# end
|
11
|
+
def self.extended(base)
|
12
|
+
unless base.respond_to?(:root)
|
13
|
+
class << base
|
14
|
+
def root
|
15
|
+
File.dirname(caller[1].split(":").first)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# class Project
|
22
|
+
# class << self
|
23
|
+
# extend Rango::ImportMixin
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
def self.included(base)
|
27
|
+
unless base.respond_to?(:root)
|
28
|
+
base.class_eval do
|
29
|
+
def root
|
30
|
+
File.dirname(caller.last.split(":").first)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# @since 0.0.1
|
37
|
+
# @example
|
38
|
+
# Project.import("blog/views")
|
39
|
+
# Project.import("blog/views", soft: true)
|
40
|
+
# @param [String] path Path to file which will be loaded using +Kernel#load+ if +Project.settings.debug+ is true or +Kernel#require+ if not.
|
41
|
+
# @param [Hash[soft: Boolean(default true)], @optional] options
|
42
|
+
# @raise [LoadError] Unless <tt>soft: true</tt> option is used, it will raise +LoadError+ if the file wasn't found.
|
43
|
+
# @return [Boolean] If loading suceed.
|
44
|
+
def import(path, options = Hash.new)
|
45
|
+
# it is better than rescue LoadError, because
|
46
|
+
# LoadError can be raise inside the required file
|
47
|
+
fullpath = self.find_absolute(path)
|
48
|
+
if fullpath.nil? && options[:soft] # any file found and soft importing enabled
|
49
|
+
# do nothing
|
50
|
+
elsif fullpath.nil? && !options[:soft] # any file found and soft importing disabled
|
51
|
+
raise LoadError, "File #{path.inspect} (treated as #{fullpath.inspect}) doesn't exist"
|
52
|
+
elsif !fullpath.nil? # the file was found
|
53
|
+
Kernel.load(fullpath)
|
54
|
+
elsif !fullpath.nil? # the file was found
|
55
|
+
Kernel.require(fullpath)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# @since 0.0.2
|
60
|
+
def import_first(paths, options = Hash.new)
|
61
|
+
paths.each do |path|
|
62
|
+
fullpath = self.find_absolute(path)
|
63
|
+
next if fullpath.nil?
|
64
|
+
return self.import(fullpath, options)
|
65
|
+
end
|
66
|
+
raise LoadError unless options[:soft]
|
67
|
+
end
|
68
|
+
|
69
|
+
# @since 0.0.1
|
70
|
+
# @param [String] path Path to loaded file.
|
71
|
+
# @return [Boolean] If the loading was successful.
|
72
|
+
def import!(path)
|
73
|
+
path = File.join(self.root, path)
|
74
|
+
file = self.find_absolute(path)
|
75
|
+
Kernel.load(file)
|
76
|
+
end
|
77
|
+
|
78
|
+
def find(file)
|
79
|
+
["#{file}.rb", file].find do |file|
|
80
|
+
File.exist?(file)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def find_absolute(file)
|
85
|
+
file = File.join(self.root, file) unless file.match(%r[^/])
|
86
|
+
self.find(file)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Include this module to strategy superclass
|
4
|
+
module RubyExts
|
5
|
+
module StrategyMixin
|
6
|
+
class << self
|
7
|
+
attribute :strategies, Array.new
|
8
|
+
|
9
|
+
def register
|
10
|
+
self.strategies.push(self)
|
11
|
+
end
|
12
|
+
|
13
|
+
def find(*args)
|
14
|
+
self.strategies.find { |strategy| strategy.match?(*args) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def match?(*args)
|
19
|
+
raise "This method must be redefined in subclasses"
|
20
|
+
end
|
21
|
+
|
22
|
+
def run(*args)
|
23
|
+
raise "This method must be redefined in subclasses"
|
24
|
+
end
|
25
|
+
|
26
|
+
# define setup method if you need it
|
27
|
+
end
|
28
|
+
end
|
data/lib/rubyexts/object.rb
CHANGED
@@ -1,26 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
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
4
|
# The opposite of <tt>#nil?</tt>.
|
25
5
|
#
|
26
6
|
# @author Botanicus
|
data/lib/rubyexts/try.rb
ADDED
@@ -0,0 +1,23 @@
|
|
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
|
+
end
|
data/lib/rubyexts.rb
CHANGED
data/rubyexts-0.0.1.gem
ADDED
Binary file
|
data/script/spec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubyexts
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Jakub \xC5\xA0\xC5\xA5astn\xC3\xBD aka Botanicus"
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain:
|
11
|
-
date: 2009-
|
11
|
+
date: 2009-12-03 00:00:00 +00:00
|
12
12
|
default_executable:
|
13
13
|
dependencies: []
|
14
14
|
|
@@ -31,6 +31,11 @@ files:
|
|
31
31
|
- lib/rubyexts/file.rb
|
32
32
|
- lib/rubyexts/hash.rb
|
33
33
|
- lib/rubyexts/kernel.rb
|
34
|
+
- lib/rubyexts/logger.rb
|
35
|
+
- lib/rubyexts/mixins/chainable.rb
|
36
|
+
- lib/rubyexts/mixins/hookable.rb
|
37
|
+
- lib/rubyexts/mixins/import.rb
|
38
|
+
- lib/rubyexts/mixins/strategy.rb
|
34
39
|
- lib/rubyexts/module.rb
|
35
40
|
- lib/rubyexts/object.rb
|
36
41
|
- lib/rubyexts/object_space.rb
|
@@ -40,6 +45,7 @@ files:
|
|
40
45
|
- lib/rubyexts/string.rb
|
41
46
|
- lib/rubyexts/time.rb
|
42
47
|
- lib/rubyexts/time_dsl.rb
|
48
|
+
- lib/rubyexts/try.rb
|
43
49
|
- lib/rubyexts/try_dup.rb
|
44
50
|
- lib/rubyexts/unique_array.rb
|
45
51
|
- lib/rubyexts.rb
|