core 0.0.6
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/README.rdoc +11 -0
- data/Rakefile +20 -0
- data/lib/core.rb +12 -0
- data/lib/core/accessor.rb +114 -0
- data/lib/core/forwardable.rb +85 -0
- data/lib/core/functor.rb +19 -0
- data/lib/core/hash.rb +13 -0
- data/lib/core/inspect.rb +20 -0
- data/lib/core/module.rb +93 -0
- data/lib/core/object.rb +64 -0
- data/lib/core/this.rb +78 -0
- data/lib/kinda-core.rb +1 -0
- data/test/__all__.rb +5 -0
- data/test/accessor_test.rb +131 -0
- data/test/forwardable_test.rb +51 -0
- data/test/module_test.rb +84 -0
- data/test/object_test.rb +28 -0
- data/test/this_test.rb +11 -0
- metadata +71 -0
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "rake/testtask"
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "hanna/rdoctask"
|
5
|
+
rescue LoadError
|
6
|
+
require "rake/rdoctask"
|
7
|
+
end
|
8
|
+
|
9
|
+
task :default => [:test]
|
10
|
+
|
11
|
+
Rake::TestTask.new do |t|
|
12
|
+
t.test_files = Dir["test/*_test.rb"]
|
13
|
+
end
|
14
|
+
|
15
|
+
Rake::RDocTask.new do |t|
|
16
|
+
t.title = "Core Documentation"
|
17
|
+
t.main = "README.rdoc"
|
18
|
+
t.rdoc_files.include("README.rdoc", "lib/**/*.rb")
|
19
|
+
t.rdoc_dir = "doc"
|
20
|
+
end
|
data/lib/core.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'core', 'module')
|
2
|
+
require File.join(File.dirname(__FILE__), 'core', 'object')
|
3
|
+
ruby_files = Dir.glob(File.join(File.dirname(__FILE__), 'core', '*.rb'))
|
4
|
+
ruby_files.each { |file| require file }
|
5
|
+
|
6
|
+
module Kinda #:nodoc:
|
7
|
+
# Basic helpers used by other kinda projects
|
8
|
+
module Core
|
9
|
+
include Accessor
|
10
|
+
include Forwardable
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module Kinda #:nodoc:
|
2
|
+
module Core #:nodoc:
|
3
|
+
# Improves the Ruby buit-in accessor methods
|
4
|
+
module Accessor
|
5
|
+
ClassMethods = inheritable_extend do
|
6
|
+
def __attr_reader__(*attributes, with_filter, &block)
|
7
|
+
attributes.each do |attribute|
|
8
|
+
if attribute.is_a?(Hash)
|
9
|
+
attribute, source = attribute.first
|
10
|
+
else
|
11
|
+
source = "@#{attribute}"
|
12
|
+
end
|
13
|
+
proc = if with_filter || !block
|
14
|
+
Proc.new do |*args|
|
15
|
+
return send("#{attribute}=", *args) unless args.empty?
|
16
|
+
value = if source[0] == '@'
|
17
|
+
instance_variable_get(source)
|
18
|
+
else
|
19
|
+
[*source].inject(self) do |object, symbol|
|
20
|
+
object.send(symbol)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
block ? instance_exec(value, &block) : value
|
24
|
+
end
|
25
|
+
else
|
26
|
+
block
|
27
|
+
end
|
28
|
+
send(:define_method, attribute, &proc)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private :__attr_reader__
|
33
|
+
|
34
|
+
# attr_reader(:name, :age, :size)
|
35
|
+
# attr_reader(:name => :@name) is the default behaviour but you can use:
|
36
|
+
# attr_reader (:name => @the_name) to use a different instance variable
|
37
|
+
# attr_reader(:name => :first_name) or even an another attribute.
|
38
|
+
# More interesting, you can delegate to another object:
|
39
|
+
# attr_reader(:name => [:father, :name])
|
40
|
+
# attr_reader(:name => [:mother, :husband, :name])
|
41
|
+
def attr_reader(*attributes, &block)
|
42
|
+
__attr_reader__(*attributes, false, &block)
|
43
|
+
end
|
44
|
+
|
45
|
+
def attr_reader_with_filter(*attributes, &block)
|
46
|
+
__attr_reader__(*attributes, true, &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def __attr_writer__(*attributes, with_filter, &block)
|
50
|
+
attributes.each do |attribute|
|
51
|
+
if attribute.is_a?(Hash)
|
52
|
+
attribute, target = attribute.first
|
53
|
+
else
|
54
|
+
target = "@#{attribute}"
|
55
|
+
end
|
56
|
+
proc = if with_filter || !block
|
57
|
+
Proc.new do |value|
|
58
|
+
value = instance_exec(value, &block) if block
|
59
|
+
if target[0] == '@'
|
60
|
+
instance_variable_set(target, value)
|
61
|
+
else
|
62
|
+
[*target][0..-2].inject(self) do |object, symbol|
|
63
|
+
object.send(symbol)
|
64
|
+
end.send("#{[*target].last}=", value)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
else
|
68
|
+
block
|
69
|
+
end
|
70
|
+
send(:define_method, "#{attribute}=", &proc)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private :__attr_writer__
|
75
|
+
|
76
|
+
def attr_writer(*attributes, &block)
|
77
|
+
__attr_writer__(*attributes, false, &block)
|
78
|
+
end
|
79
|
+
|
80
|
+
def attr_writer_with_filter(*attributes, &block)
|
81
|
+
__attr_writer__(*attributes, true, &block)
|
82
|
+
end
|
83
|
+
|
84
|
+
def attr_accessor(*attributes, &block)
|
85
|
+
attr_reader(*attributes, &block)
|
86
|
+
attr_writer(*attributes, &block)
|
87
|
+
end
|
88
|
+
|
89
|
+
def attr_accessor_with_filter(*attributes, &block)
|
90
|
+
attr_reader_with_filter(*attributes, &block)
|
91
|
+
attr_writer_with_filter(*attributes, &block)
|
92
|
+
end
|
93
|
+
|
94
|
+
def attr(attribute, writable=false)
|
95
|
+
attr_reader(attribute)
|
96
|
+
attr_writer(attribute) if writable
|
97
|
+
end
|
98
|
+
|
99
|
+
def attr_reader_with_default(attribute, default_value)
|
100
|
+
attr_reader_with_filter(attribute) do |value|
|
101
|
+
value.nil? ? default_value : value
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def attr_accessor_with_default(attribute, default_value)
|
106
|
+
attr_reader_with_default(attribute, default_value)
|
107
|
+
attr_writer(attribute)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
delegate_to_class ClassMethods.public_instance_methods
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Kinda
|
4
|
+
module Core
|
5
|
+
module Forwardable
|
6
|
+
ClassMethods = inheritable_extend do
|
7
|
+
include ::Forwardable
|
8
|
+
|
9
|
+
# Add a nice way to specify a different method for the accessor:
|
10
|
+
# delegate :remove => [:book, :delete]
|
11
|
+
# delegate [:add, :remove] => [:book, :<<, :delete]
|
12
|
+
def instance_delegate(hash)
|
13
|
+
hash.each do |delegate_methods, accessor|
|
14
|
+
accessor_methods = [*accessor]
|
15
|
+
accessor_object = accessor_methods.shift
|
16
|
+
[*delegate_methods].each do |delegate_method|
|
17
|
+
accessor_method = accessor_methods.shift || delegate_method
|
18
|
+
def_instance_delegator(accessor_object, accessor_method, delegate_method)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
alias_method :delegate, :instance_delegate
|
24
|
+
|
25
|
+
# Create both reader and writer delegate
|
26
|
+
# Same usage than the simple "delegate" method except the following form
|
27
|
+
# in case the getter and setter symbols are different:
|
28
|
+
# delegate_attr :title => [:book, [:read_title, :write_title]]
|
29
|
+
def delegate_attr_accessor(hash, kind=(:accessor), with_filter=false, &block)
|
30
|
+
hash.each do |delegate_methods, accessor|
|
31
|
+
accessor_methods = [*accessor]
|
32
|
+
accessor_object = accessor_methods.shift
|
33
|
+
[*delegate_methods].each do |delegate_method|
|
34
|
+
accessor_method = accessor_methods.shift || delegate_method
|
35
|
+
accessor_getter, accessor_setter = case kind
|
36
|
+
when :accessor
|
37
|
+
getter, setter = [*accessor_method]
|
38
|
+
setter ||= getter
|
39
|
+
[getter, setter]
|
40
|
+
when :reader
|
41
|
+
[accessor_method, nil]
|
42
|
+
when :writer
|
43
|
+
[nil, accessor_method]
|
44
|
+
end
|
45
|
+
if accessor_getter
|
46
|
+
__attr_reader__({ delegate_method => [accessor_object, accessor_getter] },
|
47
|
+
with_filter, &block)
|
48
|
+
end
|
49
|
+
if accessor_setter
|
50
|
+
__attr_writer__({ delegate_method => [accessor_object, accessor_setter] },
|
51
|
+
with_filter, &block)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
alias_method :delegate_attr, :delegate_attr_accessor
|
58
|
+
|
59
|
+
def delegate_attr_accessor_with_filter(hash, &block)
|
60
|
+
delegate_attr_accessor(hash, :accessor, true, &block)
|
61
|
+
end
|
62
|
+
|
63
|
+
alias_method :delegate_attr_with_filter, :delegate_attr_accessor_with_filter
|
64
|
+
|
65
|
+
def delegate_attr_reader(hash, &block)
|
66
|
+
delegate_attr_accessor(hash, :reader, false, &block)
|
67
|
+
end
|
68
|
+
|
69
|
+
def delegate_attr_reader_with_filter(hash, &block)
|
70
|
+
delegate_attr_accessor(hash, :reader, true, &block)
|
71
|
+
end
|
72
|
+
|
73
|
+
def delegate_attr_writer(hash, &block)
|
74
|
+
delegate_attr_accessor(hash, :writer, false, &block)
|
75
|
+
end
|
76
|
+
|
77
|
+
def delegate_attr_writer_with_filter(hash, &block)
|
78
|
+
delegate_attr_accessor(hash, :writer, true, &block)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
delegate_to_class ClassMethods.public_instance_methods
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/core/functor.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Kinda
|
2
|
+
module Core
|
3
|
+
# Thomas Sawyer's Functor Class slightly modified for Ruby 1.9
|
4
|
+
# http://facets.rubyforge.org/apidoc/api/core/classes/Functor.html
|
5
|
+
class Functor < BasicObject
|
6
|
+
def initialize(&proc)
|
7
|
+
@proc = proc
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_proc
|
11
|
+
@proc
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(method_name, *args, &block)
|
15
|
+
@proc.call(method_name, *args, &block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/core/hash.rb
ADDED
data/lib/core/inspect.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Kinda
|
2
|
+
module Core
|
3
|
+
def inspect(*args)
|
4
|
+
if %w[Bignum Class Complex Date DateTime FalseClass Fixnum Float
|
5
|
+
Integer NilClass Numeric Range Rational Regexp String Symbol
|
6
|
+
Time TrueClass].include?(self.class.name)
|
7
|
+
super()
|
8
|
+
else
|
9
|
+
result = '#<'
|
10
|
+
result += "#{self.class}:#{object_hexid}"
|
11
|
+
items = args.map do |arg|
|
12
|
+
"#{arg}=#{send(arg).inspect}" if respond_to?(arg)
|
13
|
+
end.compact
|
14
|
+
result += ' ' + items.join(', ') if !items.empty?
|
15
|
+
result += '>'
|
16
|
+
result
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/core/module.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
module Kinda
|
2
|
+
module Core
|
3
|
+
module ModuleExtension
|
4
|
+
def self.included(klass)
|
5
|
+
klass.alias_method_chain :append_features, :inheritable_extensions
|
6
|
+
end
|
7
|
+
|
8
|
+
def alias_method_chain(target, feature)
|
9
|
+
# Strip out punctuation on predicates or bang methods since
|
10
|
+
# e.g. target?_without_feature is not a valid method name.
|
11
|
+
aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
|
12
|
+
yield(aliased_target, punctuation) if block_given?
|
13
|
+
|
14
|
+
with_method, without_method =
|
15
|
+
"#{aliased_target}_with_#{feature}#{punctuation}",
|
16
|
+
"#{aliased_target}_without_#{feature}#{punctuation}"
|
17
|
+
|
18
|
+
alias_method without_method, target
|
19
|
+
alias_method target, with_method
|
20
|
+
|
21
|
+
case
|
22
|
+
when public_method_defined?(without_method)
|
23
|
+
public target
|
24
|
+
when protected_method_defined?(without_method)
|
25
|
+
protected target
|
26
|
+
when private_method_defined?(without_method)
|
27
|
+
private target
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def container
|
32
|
+
space = name[0...(name.rindex( '::' ) || 0)]
|
33
|
+
space.empty? ? Object : eval(space)
|
34
|
+
end
|
35
|
+
|
36
|
+
def extensions
|
37
|
+
singleton_class.ancestors.take_while { |mod| !mod.is_a?(Class) }
|
38
|
+
end
|
39
|
+
|
40
|
+
def inheritable_extend(*mods, &block)
|
41
|
+
if block
|
42
|
+
mod = Module.new
|
43
|
+
mod.extend extensions
|
44
|
+
mod.module_eval(&block)
|
45
|
+
mods << mod
|
46
|
+
end
|
47
|
+
extend *mods
|
48
|
+
(@inheritable_extensions ||= []).unshift(*mods.reverse).uniq!
|
49
|
+
mod
|
50
|
+
end
|
51
|
+
|
52
|
+
def append_features_with_inheritable_extensions(target)
|
53
|
+
append_features_without_inheritable_extensions(target)
|
54
|
+
if @inheritable_extensions
|
55
|
+
target.extend *@inheritable_extensions
|
56
|
+
target.inheritable_extend *@inheritable_extensions.reverse
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# delegate_to_class :singleton_method_added => :method_added
|
61
|
+
# delegate_to_class [:attr_reader, :attr_writer]
|
62
|
+
# delegate_to_class ClassMethods.instance_methods
|
63
|
+
def delegate_to_class(*sources)
|
64
|
+
sources, target = sources.first.first if sources.first.is_a?(Hash)
|
65
|
+
[*sources].flatten.each do |source|
|
66
|
+
define_method(source) do |*args, &block|
|
67
|
+
singleton_class_send(target || source, *args, &block)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self_and_ancestors
|
73
|
+
result = ancestors
|
74
|
+
result.unshift self unless result.first == self
|
75
|
+
result
|
76
|
+
end
|
77
|
+
|
78
|
+
def ancestors_without_self
|
79
|
+
result = ancestors
|
80
|
+
result.first == self ? result.drop(1) : result
|
81
|
+
end
|
82
|
+
|
83
|
+
def ancestor
|
84
|
+
ancestors_without_self.first
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class Module #:nodoc:
|
91
|
+
include Kinda::Core::ModuleExtension
|
92
|
+
end
|
93
|
+
|
data/lib/core/object.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
module Kinda
|
2
|
+
module Core
|
3
|
+
module ObjectExtension
|
4
|
+
def self.included(klass)
|
5
|
+
klass.alias_method_chain :extend, :flexible_arguments
|
6
|
+
end
|
7
|
+
|
8
|
+
def object_hexid
|
9
|
+
"0x" + ('%.x' % (self.__id__ * 2))
|
10
|
+
end
|
11
|
+
|
12
|
+
def singleton_class
|
13
|
+
class << self; self; end
|
14
|
+
end
|
15
|
+
|
16
|
+
def singleton_class_eval(&block)
|
17
|
+
singleton_class.class_eval(&block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def singleton_class_send(method_name, *args, &block)
|
21
|
+
singleton_class_eval { send(method_name, *args, &block) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_class
|
25
|
+
kind_of?(Module) ? self : singleton_class
|
26
|
+
end
|
27
|
+
|
28
|
+
alias_method :to_module, :to_class
|
29
|
+
|
30
|
+
def extend_with_flexible_arguments(*modules)
|
31
|
+
mods = modules.flatten
|
32
|
+
extend_without_flexible_arguments(*mods) unless mods.empty?
|
33
|
+
end
|
34
|
+
|
35
|
+
def tap
|
36
|
+
return super if block_given?
|
37
|
+
Functor.new { |method, *args| self.send(method, *args); self }
|
38
|
+
end
|
39
|
+
|
40
|
+
def try(method_name, *args, &block)
|
41
|
+
send(method_name, *args, &block) if respond_to?(method_name)
|
42
|
+
end
|
43
|
+
|
44
|
+
def receiver
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
alias_method :__instance_exec__, :instance_exec
|
49
|
+
|
50
|
+
def parse_arguments(args, *defaults)
|
51
|
+
args = args.dup
|
52
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
53
|
+
raise ArgumentError, "Too many arguments (#{args.size} for #{defaults.size})" if
|
54
|
+
args.size > defaults.size
|
55
|
+
defaults.drop(args.size).each { |default| args << default }
|
56
|
+
args << options
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class Object #:nodoc:
|
63
|
+
include Kinda::Core::ObjectExtension
|
64
|
+
end
|
data/lib/core/this.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
module Kinda
|
2
|
+
module Core
|
3
|
+
module This
|
4
|
+
module ProcExtension
|
5
|
+
def call_with_this(this, *args, &block)
|
6
|
+
binding_self = binding.eval('self')
|
7
|
+
binding_self.push_this(this)
|
8
|
+
call(*args, &block)
|
9
|
+
ensure
|
10
|
+
binding_self.pop_this
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
###
|
15
|
+
|
16
|
+
def call_with_this(proc, *args, &block)
|
17
|
+
return unless proc
|
18
|
+
binding_self = proc.binding.eval('self')
|
19
|
+
raise "Object #{binding_self.inspect} doesn't respond to Kinda::Core::This methods " +
|
20
|
+
"(proc=#{proc.inspect})" unless binding_self.respond_to?(:push_this)
|
21
|
+
begin
|
22
|
+
binding_self.push_this(self)
|
23
|
+
proc.call(*args, &block)
|
24
|
+
ensure
|
25
|
+
binding_self.pop_this
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def push_this(object)
|
30
|
+
(@these ||= []).push(object)
|
31
|
+
end
|
32
|
+
|
33
|
+
def pop_this
|
34
|
+
@these.pop if @these
|
35
|
+
end
|
36
|
+
|
37
|
+
def this
|
38
|
+
(@these && @these.last) || self
|
39
|
+
end
|
40
|
+
|
41
|
+
def this_eval(&block)
|
42
|
+
this.instance_eval(&block)
|
43
|
+
end
|
44
|
+
|
45
|
+
attr_reader :contextual_methods
|
46
|
+
|
47
|
+
def contextual_method(*methods)
|
48
|
+
methods.each do |method|
|
49
|
+
(@contextual_methods ||= []) << method.to_sym
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def contextual_method?(method)
|
54
|
+
to_class.self_and_ancestors.each do |ancestor|
|
55
|
+
return true if ancestor.contextual_methods &&
|
56
|
+
ancestor.contextual_methods.include?(method.to_sym)
|
57
|
+
end
|
58
|
+
false
|
59
|
+
end
|
60
|
+
|
61
|
+
def method_missing(method_name, *args, &block)
|
62
|
+
if this != self && this.contextual_method?(method_name)
|
63
|
+
this.send(method_name, *args, &block)
|
64
|
+
else
|
65
|
+
super
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class Object #:nodoc:
|
73
|
+
include Kinda::Core::This
|
74
|
+
end
|
75
|
+
|
76
|
+
class Proc #:nodoc:
|
77
|
+
include Kinda::Core::This::ProcExtension
|
78
|
+
end
|
data/lib/kinda-core.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'core')
|
data/test/__all__.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
#!/usr/bin/ruby19
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')).uniq!
|
7
|
+
require 'kinda-core'
|
8
|
+
|
9
|
+
class AccessorTest < Test::Unit::TestCase
|
10
|
+
def setup
|
11
|
+
@human_class = Class.new do
|
12
|
+
include Kinda::Core
|
13
|
+
end
|
14
|
+
@human = @human_class.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_attribute_defined_at_class_level
|
18
|
+
@human_class.class_eval do
|
19
|
+
attr_accessor :name
|
20
|
+
end
|
21
|
+
assert_nil @human.name
|
22
|
+
@human.name = 'Dave'
|
23
|
+
assert_equal 'Dave', @human.name
|
24
|
+
@human.name 'Fred'
|
25
|
+
assert_equal 'Fred', @human.name
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_attribute_defined_at_instance_level
|
29
|
+
@human.attr_accessor :name
|
30
|
+
assert_nil @human.name
|
31
|
+
@human.name = 'Dave'
|
32
|
+
assert_equal 'Dave', @human.name
|
33
|
+
@human.name 'Fred'
|
34
|
+
assert_equal 'Fred', @human.name
|
35
|
+
@other_human = @human_class.new
|
36
|
+
assert_raise NoMethodError do
|
37
|
+
@other_human.name
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_attribute_with_block_defined_at_class_level
|
42
|
+
@human_class.class_eval do
|
43
|
+
attr_reader :name do |capitalize=false|
|
44
|
+
capitalize ? @the_name.capitalize : @the_name
|
45
|
+
end
|
46
|
+
attr_writer :name do |value|
|
47
|
+
@the_name = value
|
48
|
+
end
|
49
|
+
end
|
50
|
+
assert_equal nil, @human.name
|
51
|
+
@human.name = 'Dave'
|
52
|
+
assert_equal 'Dave', @human.name
|
53
|
+
@human.name = 'fred'
|
54
|
+
assert_equal 'Fred', @human.name(true)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_attribute_with_filter_defined_at_class_level
|
58
|
+
@human_class.class_eval do
|
59
|
+
attr_accessor :nickname
|
60
|
+
|
61
|
+
attr_reader_with_filter :name do |value|
|
62
|
+
value || nickname || 'Mike'
|
63
|
+
end
|
64
|
+
attr_writer_with_filter :name do |value|
|
65
|
+
value.capitalize
|
66
|
+
end
|
67
|
+
end
|
68
|
+
assert_equal 'Mike', @human.name
|
69
|
+
@human.nickname = 'Mikey'
|
70
|
+
assert_equal 'Mikey', @human.name
|
71
|
+
@human.name = 'dave'
|
72
|
+
assert_equal 'Dave', @human.name
|
73
|
+
@human.name 'FRED'
|
74
|
+
assert_equal 'Fred', @human.name
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_attribute_redirection
|
78
|
+
@human.attr_accessor :name => :@the_name
|
79
|
+
assert_nil @human.name
|
80
|
+
@human.name = 'Dave'
|
81
|
+
assert_equal 'Dave', @human.name
|
82
|
+
assert_equal 'Dave', @human.instance_variable_get(:@the_name)
|
83
|
+
@human.name = 'Fred'
|
84
|
+
assert_equal 'Fred', @human.name
|
85
|
+
@human.attr_accessor :last_name => :name
|
86
|
+
assert_equal 'Fred', @human.last_name
|
87
|
+
@human.last_name = 'Mike'
|
88
|
+
assert_equal 'Mike', @human.last_name
|
89
|
+
assert_equal 'Mike', @human.name
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_attribute_delegation
|
93
|
+
@child = @human_class.new
|
94
|
+
@father = @human_class.new
|
95
|
+
@child.attr_accessor :father
|
96
|
+
@child.father = @father
|
97
|
+
assert_equal @father, @child.father
|
98
|
+
@father.attr_accessor :name
|
99
|
+
@father.name = 'Dave'
|
100
|
+
@child.attr_accessor :name => [:father, :name]
|
101
|
+
assert_equal 'Dave', @child.name
|
102
|
+
@child.name = 'Fred'
|
103
|
+
assert_equal 'Fred', @child.name
|
104
|
+
assert_equal 'Fred', @father.name
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_attribute_double_delegation
|
108
|
+
@child = @human_class.new
|
109
|
+
@mother = @human_class.new
|
110
|
+
@husband = @human_class.new
|
111
|
+
@child.attr_accessor :mother
|
112
|
+
@child.mother = @mother
|
113
|
+
@mother.attr_accessor :husband
|
114
|
+
@mother.husband = @husband
|
115
|
+
assert_equal @husband, @child.mother.husband
|
116
|
+
@husband.attr_accessor :name
|
117
|
+
@husband.name = 'Dave'
|
118
|
+
@child.attr_accessor :name => [:mother, :husband, :name]
|
119
|
+
assert_equal 'Dave', @child.name
|
120
|
+
@child.name = 'Fred'
|
121
|
+
assert_equal 'Fred', @child.name
|
122
|
+
assert_equal 'Fred', @husband.name
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_attribute_with_default
|
126
|
+
@human.attr_accessor_with_default :name, 'Bart'
|
127
|
+
assert_equal 'Bart', @human.name
|
128
|
+
@human.name = 'Dave'
|
129
|
+
assert_equal 'Dave', @human.name
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/usr/bin/ruby19
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')).uniq!
|
7
|
+
require 'kinda-core'
|
8
|
+
|
9
|
+
class ForwardableTest < Test::Unit::TestCase
|
10
|
+
def setup
|
11
|
+
@human_class = Class.new do
|
12
|
+
include Kinda::Core
|
13
|
+
end
|
14
|
+
@human = @human_class.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_delegate_attribute
|
18
|
+
@child = @human_class.new
|
19
|
+
@father = @human_class.new
|
20
|
+
@child.attr_accessor :father
|
21
|
+
@child.father = @father
|
22
|
+
assert_equal @father, @child.father
|
23
|
+
@father.attr_accessor :name
|
24
|
+
@father.name = 'Dave'
|
25
|
+
@child.delegate_attr :name => :father
|
26
|
+
assert_equal 'Dave', @child.name
|
27
|
+
@child.name = 'Fred'
|
28
|
+
assert_equal 'Fred', @child.name
|
29
|
+
assert_equal 'Fred', @father.name
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_delegate_attribute_with_filter
|
33
|
+
@child = @human_class.new
|
34
|
+
@father = @human_class.new
|
35
|
+
@child.attr_accessor :father
|
36
|
+
@child.father = @father
|
37
|
+
assert_equal @father, @child.father
|
38
|
+
@father.attr_accessor :name
|
39
|
+
@father.name = 'Dave'
|
40
|
+
@child.delegate_attr_reader_with_filter :name => :father do |value|
|
41
|
+
value + ' junior'
|
42
|
+
end
|
43
|
+
assert_equal 'Dave junior', @child.name
|
44
|
+
@child.delegate_attr_writer_with_filter :name => :father do |value|
|
45
|
+
value.capitalize
|
46
|
+
end
|
47
|
+
@child.name = 'fred'
|
48
|
+
assert_equal 'Fred junior', @child.name
|
49
|
+
assert_equal 'Fred', @father.name
|
50
|
+
end
|
51
|
+
end
|
data/test/module_test.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
#!/usr/bin/ruby19
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')).uniq!
|
7
|
+
require 'kinda-core'
|
8
|
+
|
9
|
+
class ModuleTest < Test::Unit::TestCase
|
10
|
+
def meth
|
11
|
+
'meth'
|
12
|
+
end
|
13
|
+
|
14
|
+
def meth_with_upcase
|
15
|
+
meth_without_upcase.upcase
|
16
|
+
end
|
17
|
+
|
18
|
+
alias_method_chain :meth, :upcase
|
19
|
+
|
20
|
+
def test_alias_method_chain
|
21
|
+
assert_equal 'METH', meth
|
22
|
+
end
|
23
|
+
|
24
|
+
$meth2 = []
|
25
|
+
|
26
|
+
module A
|
27
|
+
module ClassMethods1
|
28
|
+
def meth1
|
29
|
+
'meth1'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module ClassMethods2
|
34
|
+
def meth2
|
35
|
+
$meth2 << 'ClassMethods2.meth2'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
inheritable_extend ClassMethods1, ClassMethods2
|
40
|
+
end
|
41
|
+
|
42
|
+
module B
|
43
|
+
include A
|
44
|
+
|
45
|
+
ClassMethods3 = inheritable_extend do
|
46
|
+
$meth1 = meth1
|
47
|
+
|
48
|
+
def meth3
|
49
|
+
'meth3'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
module ClassMethods4
|
54
|
+
def meth2
|
55
|
+
super
|
56
|
+
$meth2 << 'ClassMethods4.meth2'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
inheritable_extend ClassMethods4
|
61
|
+
end
|
62
|
+
|
63
|
+
class X
|
64
|
+
include B
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_container
|
68
|
+
assert_equal ModuleTest::A, ModuleTest::A::ClassMethods1.container
|
69
|
+
assert_equal ModuleTest::B, ModuleTest::B::ClassMethods3.container
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_extensions
|
73
|
+
assert_equal [ModuleTest::B::ClassMethods4, ModuleTest::B::ClassMethods3,
|
74
|
+
ModuleTest::A::ClassMethods2, ModuleTest::A::ClassMethods1], X.extensions
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_inheritable_extend
|
78
|
+
assert_equal 'meth1', $meth1
|
79
|
+
X.meth2
|
80
|
+
assert_equal ["ClassMethods2.meth2", "ClassMethods4.meth2"], $meth2
|
81
|
+
assert_equal 'meth1', X.meth1
|
82
|
+
assert_equal 'meth3', X.meth3
|
83
|
+
end
|
84
|
+
end
|
data/test/object_test.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/ruby19
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'test/unit'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')).uniq!
|
7
|
+
require 'kinda-core'
|
8
|
+
|
9
|
+
class ObjectTest < Test::Unit::TestCase
|
10
|
+
def test_tap
|
11
|
+
assert_equal 'Hello', 'Hello'.tap { |str| assert_equal 'HELLO', str.upcase }
|
12
|
+
assert_equal 'Hello', 'Hello'.tap.upcase
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_try
|
16
|
+
assert_equal nil, 'Hello'.try(:undefined)
|
17
|
+
assert_equal 'HELLO', 'Hello'.try(:upcase)
|
18
|
+
assert_equal 'hello', 'Hello'.try(:upcase).try(:downcase)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_parse_arguments
|
22
|
+
assert_equal [1, 2, {}], parse_arguments([], 1, 2)
|
23
|
+
assert_equal [3, 4, {}], parse_arguments([3, 4], 1, 2)
|
24
|
+
assert_raise(ArgumentError) { parse_arguments([3, 4, 5], 1, 2) }
|
25
|
+
assert_equal [1, 2, {:a => 'c', :b => 'd'}], parse_arguments([:a => 'c', :b => 'd'], 1, 2)
|
26
|
+
assert_equal [3, 2, {:a => 'c', :b => 'd'}], parse_arguments([3, :a => 'c', :b => 'd'], 1, 2)
|
27
|
+
end
|
28
|
+
end
|
data/test/this_test.rb
ADDED
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: core
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.6
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Manuel Vila
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-12 00:00:00 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Basic helpers used by other kinda projects
|
17
|
+
email: mvila@3base.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rdoc
|
24
|
+
files:
|
25
|
+
- Rakefile
|
26
|
+
- lib/core.rb
|
27
|
+
- lib/kinda-core.rb
|
28
|
+
- lib/core/accessor.rb
|
29
|
+
- lib/core/forwardable.rb
|
30
|
+
- lib/core/functor.rb
|
31
|
+
- lib/core/hash.rb
|
32
|
+
- lib/core/inspect.rb
|
33
|
+
- lib/core/module.rb
|
34
|
+
- lib/core/object.rb
|
35
|
+
- lib/core/this.rb
|
36
|
+
- README.rdoc
|
37
|
+
has_rdoc: true
|
38
|
+
homepage: http://github.com/kinda/core
|
39
|
+
licenses: []
|
40
|
+
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: 1.9.1
|
51
|
+
version:
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
version:
|
58
|
+
requirements: []
|
59
|
+
|
60
|
+
rubyforge_project: kinda-core
|
61
|
+
rubygems_version: 1.3.5
|
62
|
+
signing_key:
|
63
|
+
specification_version: 3
|
64
|
+
summary: Basic helpers used by other kinda projects
|
65
|
+
test_files:
|
66
|
+
- test/__all__.rb
|
67
|
+
- test/accessor_test.rb
|
68
|
+
- test/forwardable_test.rb
|
69
|
+
- test/module_test.rb
|
70
|
+
- test/object_test.rb
|
71
|
+
- test/this_test.rb
|