kinda-core 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,14 @@
1
+ Author:: Manuel Vila (mailto:mvila@3base.com)
2
+ License:: Don't know yet
3
+
4
+ = Core
5
+
6
+ Basic helpers used by other kinda projects.
7
+
8
+ == Installation
9
+
10
+ $ sudo gem install kinda-core --source http://gems.github.com
11
+
12
+ == Usage
13
+
14
+ Still very alpha so documentation will come later.
@@ -0,0 +1,110 @@
1
+ module Kinda
2
+ module Core
3
+ module Accessor
4
+ module ClassMethods
5
+ # attr_reader(:name, :age, :size)
6
+ # attr_reader(:name => :@name) is the default behaviour but you can use:
7
+ # attr_reader (:name => @the_name) to use a different instance variable
8
+ # attr_reader(:name => :first_name) or even an another attribute.
9
+ # But more interesting, you can delegate to another object:
10
+ # attr_reader(:name => [:father, :name])
11
+ # attr_reader(:name => [:mother, :husband, :name])
12
+ def __attr_reader__(*attributes, with_filter, &block)
13
+ attributes.each do |attribute|
14
+ if attribute.is_a?(Hash)
15
+ attribute, source = attribute.first
16
+ else
17
+ source = "@#{attribute}"
18
+ end
19
+ proc = if with_filter || !block
20
+ ::Proc.new do |*args|
21
+ return send("#{attribute}=", *args) unless args.empty?
22
+ value = if source[0] == '@'
23
+ instance_variable_get(source)
24
+ else
25
+ [*source].inject(self) do |object, symbol|
26
+ object.send(symbol)
27
+ end
28
+ end
29
+ block ? instance_exec(value, &block) : value
30
+ end
31
+ else
32
+ block
33
+ end
34
+ to_class.send(:define_method, attribute, &proc)
35
+ end
36
+ end
37
+
38
+ def attr_reader(*attributes, &block)
39
+ __attr_reader__(*attributes, false, &block)
40
+ end
41
+
42
+ def attr_reader_with_filter(*attributes, &block)
43
+ __attr_reader__(*attributes, true, &block)
44
+ end
45
+
46
+ def __attr_writer__(*attributes, with_filter, &block)
47
+ attributes.each do |attribute|
48
+ if attribute.is_a?(Hash)
49
+ attribute, target = attribute.first
50
+ else
51
+ target = "@#{attribute}"
52
+ end
53
+ proc = if with_filter || !block
54
+ ::Proc.new do |value|
55
+ value = instance_exec(value, &block) if block
56
+ if target[0] == '@'
57
+ instance_variable_set(target, value)
58
+ else
59
+ [*target][0..-2].inject(self) do |object, symbol|
60
+ object.send(symbol)
61
+ end.send("#{[*target].last}=", value)
62
+ end
63
+ end
64
+ else
65
+ block
66
+ end
67
+ to_class.send(:define_method, "#{attribute}=", &proc)
68
+ end
69
+ end
70
+
71
+ def attr_writer(*attributes, &block)
72
+ __attr_writer__(*attributes, false, &block)
73
+ end
74
+
75
+ def attr_writer_with_filter(*attributes, &block)
76
+ __attr_writer__(*attributes, true, &block)
77
+ end
78
+
79
+ def attr_accessor(*attributes, &block)
80
+ attr_reader(*attributes, &block)
81
+ attr_writer(*attributes, &block)
82
+ end
83
+
84
+ def attr_accessor_with_filter(*attributes, &block)
85
+ attr_reader_with_filter(*attributes, &block)
86
+ attr_writer_with_filter(*attributes, &block)
87
+ end
88
+
89
+ def attr(attribute, writable=false)
90
+ attr_reader(attribute)
91
+ attr_writer(attribute) if writable
92
+ end
93
+
94
+ def attr_reader_with_default(attribute, default_value)
95
+ attr_reader_with_filter(attribute) do |value|
96
+ value.nil? ? default_value : value
97
+ end
98
+ end
99
+
100
+ def attr_accessor_with_default(attribute, default_value)
101
+ attr_reader_with_default(attribute, default_value)
102
+ attr_writer(attribute)
103
+ end
104
+ end
105
+
106
+ include ClassMethods
107
+ inheritable_extension ClassMethods
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,86 @@
1
+ require 'forwardable'
2
+
3
+ module Kinda
4
+ module Core
5
+ module Forwardable
6
+ module ClassMethods
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
+ include ClassMethods
83
+ inheritable_extension ClassMethods
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,19 @@
1
+ # Thomas Sawyer's Functor Class slightly modified for Ruby 1.9
2
+ # http://facets.rubyforge.org/apidoc/api/core/classes/Functor.html
3
+ module Kinda
4
+ module Core
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
@@ -0,0 +1,13 @@
1
+ module Kinda
2
+ module Core
3
+ module Hash
4
+ def delete_value(value)
5
+ delete_if { |k, v| v == value }
6
+ end
7
+ end
8
+ end
9
+ end
10
+
11
+ class Hash
12
+ include Kinda::Core::Hash
13
+ end
@@ -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
@@ -0,0 +1,81 @@
1
+ module Kinda
2
+ module Core
3
+ module Module
4
+ def self.included(klass)
5
+ klass.alias_method_chain :append_features, :module_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_extension(*mods)
41
+ (@inheritable_extensions ||= []).unshift(mods.reverse).flatten!.uniq!
42
+ end
43
+
44
+ def append_features_with_module_extensions(target)
45
+ append_features_without_module_extensions(target)
46
+ if @inheritable_extensions
47
+ target.extend *@inheritable_extensions
48
+ target.inheritable_extension *@inheritable_extensions.reverse
49
+ end
50
+ end
51
+
52
+ def delegate_to_class(source, target=source)
53
+ define_method(source) do |*args, &block|
54
+ singleton_class_eval do
55
+ send(target, *args, &block)
56
+ end
57
+ end
58
+ end
59
+
60
+ def self_and_ancestors
61
+ result = ancestors
62
+ result.unshift self unless result.first == self
63
+ result
64
+ end
65
+
66
+ def ancestors_without_self
67
+ result = ancestors
68
+ result.first == self ? result.drop(1) : result
69
+ end
70
+
71
+ def ancestor
72
+ ancestors_without_self.first
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ class Module
79
+ include Kinda::Core::Module
80
+ end
81
+
@@ -0,0 +1,63 @@
1
+ module Kinda
2
+ module Core
3
+ module Object
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 to_class
21
+ kind_of?(Module) ? self : singleton_class
22
+ end
23
+
24
+ alias_method :to_module, :to_class
25
+
26
+ def extend_with_flexible_arguments(*modules)
27
+ mods = modules.flatten
28
+ extend_without_flexible_arguments(*mods) unless mods.empty?
29
+ end
30
+
31
+ def tap
32
+ return super if block_given?
33
+ Functor.new { |method, *args| self.send(method, *args); self }
34
+ end
35
+
36
+ def try(methods, *args, &block)
37
+ methods = [*methods].dup
38
+ return self if methods.empty?
39
+ send(methods.shift, *args, &block).try(methods, *args, &block) if
40
+ respond_to?(methods.first)
41
+ end
42
+
43
+ def receiver
44
+ self
45
+ end
46
+
47
+ alias_method :__instance_exec__, :instance_exec
48
+
49
+ def parse_arguments(args, *defaults)
50
+ args = args.dup
51
+ options = args.last.is_a?(Hash) ? args.pop : {}
52
+ raise ArgumentError, "Too many arguments (#{args.size} for #{defaults.size})" if
53
+ args.size > defaults.size
54
+ defaults.drop(args.size).each { |default| args << default }
55
+ args << options
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ class Object
62
+ include Kinda::Core::Object
63
+ end
data/lib/core/proc.rb ADDED
@@ -0,0 +1,17 @@
1
+ module Kinda
2
+ module Core
3
+ module Proc
4
+ def call_with_this(this, *args, &block)
5
+ binding_self = binding.eval('self')
6
+ binding_self.push_this(this)
7
+ call(*args, &block)
8
+ ensure
9
+ binding_self.pop_this
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ class Proc
16
+ include Kinda::Core::Proc
17
+ end
data/lib/core/this.rb ADDED
@@ -0,0 +1,62 @@
1
+ module Kinda
2
+ module Core
3
+ module This
4
+ def call_with_this(proc, *args, &block)
5
+ return unless proc
6
+ binding_self = proc.binding.eval('self')
7
+ raise "Object #{binding_self.inspect} doesn't respond to Kinda::Core::This methods " +
8
+ "(proc=#{proc.inspect})" unless binding_self.respond_to?(:push_this)
9
+ begin
10
+ binding_self.push_this(self)
11
+ proc.call(*args, &block)
12
+ ensure
13
+ binding_self.pop_this
14
+ end
15
+ end
16
+
17
+ def push_this(object)
18
+ (@these ||= []).push(object)
19
+ end
20
+
21
+ def pop_this
22
+ @these.pop if @these
23
+ end
24
+
25
+ def this
26
+ (@these && @these.last) || self
27
+ end
28
+
29
+ def this_eval(&block)
30
+ this.instance_eval(&block)
31
+ end
32
+
33
+ attr_reader :contextual_methods
34
+
35
+ def contextual_method(*methods)
36
+ methods.each do |method|
37
+ (@contextual_methods ||= []) << method.to_sym
38
+ end
39
+ end
40
+
41
+ def contextual_method?(method)
42
+ to_class.self_and_ancestors.each do |ancestor|
43
+ return true if ancestor.contextual_methods &&
44
+ ancestor.contextual_methods.include?(method.to_sym)
45
+ end
46
+ false
47
+ end
48
+
49
+ def method_missing(method_name, *args, &block)
50
+ if this != self && this.contextual_method?(method_name)
51
+ this.send(method_name, *args, &block)
52
+ else
53
+ super
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ class Object
61
+ include Kinda::Core::This
62
+ end
data/lib/core.rb ADDED
@@ -0,0 +1,10 @@
1
+ require File.join(File.dirname(__FILE__), 'kinda-core', 'module')
2
+ ruby_files = Dir.glob(File.join(File.dirname(__FILE__), 'kinda-core', '*.rb'))
3
+ ruby_files.each { |file| require file }
4
+
5
+ module Kinda
6
+ module Core
7
+ include Accessor
8
+ include Forwardable
9
+ end
10
+ end
data/lib/kinda-core.rb ADDED
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), 'core')
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kinda-core
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Manuel Vila
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-16 00:00:00 -07: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
+ - lib/core.rb
26
+ - lib/core/accessor.rb
27
+ - lib/core/forwardable.rb
28
+ - lib/core/functor.rb
29
+ - lib/core/hash.rb
30
+ - lib/core/inspect.rb
31
+ - lib/core/module.rb
32
+ - lib/core/object.rb
33
+ - lib/core/proc.rb
34
+ - lib/core/this.rb
35
+ - lib/kinda-core.rb
36
+ - README.rdoc
37
+ has_rdoc: true
38
+ homepage: http://github.com/kinda/core
39
+ licenses:
40
+ post_install_message:
41
+ rdoc_options: []
42
+
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
57
+ requirements: []
58
+
59
+ rubyforge_project: kinda-core
60
+ rubygems_version: 1.3.5
61
+ signing_key:
62
+ specification_version: 2
63
+ summary: Basic helpers used by other kinda projects
64
+ test_files: []
65
+