rns 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rns (0.0.2)
4
+ rns (0.0.3)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
data/README.md CHANGED
@@ -24,10 +24,8 @@ module Statistics
24
24
  end
25
25
 
26
26
  class Main
27
- include Rns
28
-
29
- extend_specified Arithmetic => [:inc]
30
- include_specified Statistics => [:avg]
27
+ extend Rns.module_with(Arithmetic => [:inc])
28
+ include Rns.module_with(Statistics => [:avg])
31
29
 
32
30
  def main
33
31
  puts "1+1 is #{self.class.inc 1} and the average of [1,2,3] is #{avg [1,2,3]}"
data/lib/rns/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rns
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/lib/rns.rb CHANGED
@@ -1,41 +1,47 @@
1
1
  module Rns
2
- def self.included(base)
3
- base.extend(ClassMethods)
4
- end
2
+ class << self
3
+ def constant_for(module_names)
4
+ (m, *more) = module_names.map{|n| n.split("::")}.flatten
5
+ more.reduce(Kernel.const_get(m)){|m, s| m.const_get(s)}
6
+ end
5
7
 
6
- def self.add_methods(to, use_spec)
7
- use_spec.to_a.each do |from, method_names|
8
- if (method_names.is_a? Hash)
9
- add_methods(to, method_names.map do |k,v|
10
- #TODO: is there a better way to construct modules?
11
- {eval(from.to_s + "::" + k.to_s) => v}
12
- end.reduce({}){|l,r| l.merge(r)})
13
- else
14
- method_names.each do |name|
15
- if (name.is_a? Hash)
16
- add_methods(to, {from => name})
17
- else
18
- to.send(:define_method, name) do |*args|
19
- from.method(name).call(*args)
20
- end
21
- end
8
+ def module_with(use_spec)
9
+ Module.new.tap {|m| add_methods(m, use_spec) }
10
+ end
11
+
12
+ def process_spec_entry(entry)
13
+ (k,v) = entry
14
+ if (v.is_a? Array)
15
+ v.map{|x| process_spec_entry([k,x])}
16
+ elsif (v.is_a? Hash)
17
+ v.map do |x,y|
18
+ process_spec_entry([constant_for([k, x].map(&:to_s)), y])
22
19
  end
20
+ else
21
+ [k,v]
23
22
  end
24
23
  end
25
- end
26
24
 
27
- module ClassMethods
28
- def include_specified(use_spec)
29
- Rns::add_methods(self, use_spec)
25
+ def process_spec(use_spec)
26
+ use_spec.map(&method(:process_spec_entry)).
27
+ flatten.
28
+ each_slice(2).
29
+ to_a
30
30
  end
31
31
 
32
- def extend_specified(use_spec)
33
- singleton_class = class << self; self; end
34
- Rns::add_methods(singleton_class, use_spec)
32
+ def add_methods(to, use_spec)
33
+ process_spec(use_spec).each do |from, method|
34
+ to.send(:define_method, method) do |*args|
35
+ from.method(method).call(*args)
36
+ end
37
+ to.send(:private, method)
38
+ end
35
39
  end
36
- end
37
40
 
38
- def self.using(use_spec, &blk)
39
- blk[Object.new.tap{|o| Rns::add_methods(o.class, use_spec)}]
41
+ def using(use_spec, &blk)
42
+ klass = Class.new
43
+ add_methods(klass, use_spec)
44
+ klass.new.instance_eval(&blk)
45
+ end
40
46
  end
41
47
  end
data/spec/rns/rns_spec.rb CHANGED
@@ -8,6 +8,7 @@ module Math
8
8
  class << self
9
9
  def dec(n) n - one end
10
10
  def inc(n) n + one end
11
+ def add(x,y) x + y end
11
12
  private
12
13
  def one() 1 end
13
14
  end
@@ -15,17 +16,40 @@ module Math
15
16
 
16
17
  module Statistics
17
18
  def self.avg(arr); arr.reduce(:+).to_f / arr.count end
19
+ module Foo
20
+ def self.blah; :quux end
21
+ end
18
22
  end
19
23
  end
20
24
 
21
- class Thing
22
- include Rns
25
+ module Util
26
+ class << self
27
+ def assoc!(h, k, v)
28
+ h.tap{|o| o[k] = v}
29
+ end
23
30
 
24
- extend_specified Math::Arithmetic => [:inc]
25
- include_specified Math::Statistics => [:avg]
31
+ def merge_with(f, *hshs)
32
+ merge_entry = lambda do |h, (k,v)|
33
+ if (h.has_key?(k))
34
+ assoc!(h, k, f[h[k], v])
35
+ else
36
+ assoc!(h, k, v)
37
+ end
38
+ end
39
+ merge2 = lambda do |h1,h2|
40
+ h2.to_a.reduce(h1, &merge_entry)
41
+ end
42
+ ([{}] + hshs).reduce(&merge2)
43
+ end
44
+ end
45
+ end
26
46
 
27
- def inced_one
28
- self.class.inc 1
47
+ class Thing
48
+ extend Rns.module_with(Math::Arithmetic => [:inc])
49
+ include Rns.module_with(Math::Statistics => [:avg])
50
+
51
+ def self.inced_one
52
+ inc 1
29
53
  end
30
54
 
31
55
  def average
@@ -40,11 +64,33 @@ describe Rns do
40
64
  end
41
65
 
42
66
  it "works with private module methods" do
43
- Thing.new.inced_one.should == 2
67
+ Thing.inced_one.should == 2
68
+ end
69
+
70
+ it "should add methods privately" do
71
+ lambda { Thing.new.avg [11, 42, 7] }.should raise_error(NoMethodError)
44
72
  end
45
73
  end
46
74
 
47
75
  context 'adding methods to blocks' do
76
+
77
+ it 'computes' do
78
+ Rns::using(Util => [:merge_with],
79
+ Math::Arithmetic => [:inc, :add]) do
80
+
81
+ sum = lambda{|*xs| xs.reduce(:+)}
82
+
83
+ merge_with(sum, *(1..10).map{|n| {x: n}})[:x].should == 55
84
+ merge_with(sum,
85
+ {x: 10, y: 20},
86
+ {x: 3, z: 30}).should == {x: 13, y: 20, z: 30}
87
+
88
+ merge_with(lambda{|l,r| l.send(:+, r)},
89
+ {:x => [:something]},
90
+ {:x => [:else]}).should == {:x => [:something, :else]}
91
+ end
92
+ end
93
+
48
94
  it "works with individual modules" do
49
95
  Rns::using(Math::Arithmetic => [:inc],
50
96
  Math::Statistics => [:avg]) do
@@ -68,5 +114,38 @@ describe Rns do
68
114
  avg((1..10).to_a.map(&method(:inc))).should == 6.5
69
115
  end
70
116
  end
117
+
118
+ it "does not modify Object" do
119
+ Rns::using(Math::Arithmetic => [:inc]) do
120
+ # do nothing
121
+ end
122
+ lambda { Object.new.inc 1 }.should raise_error(NoMethodError)
123
+ end
124
+
125
+ it "does not modify Class" do
126
+ Rns::using(Math::Arithmetic => [:inc]) do
127
+ # do nothing
128
+ end
129
+ lambda { Class.new.inc 1 }.should raise_error(NoMethodError)
130
+ end
131
+
132
+ it 'processes specs correctly' do
133
+ Rns::using(Rns => [:process_spec]) do
134
+ process_spec({Math => [:inc, :dec]}).
135
+ should == [[Math, :inc], [Math, :dec]]
136
+ end
137
+
138
+ Rns::using(Rns => [:process_spec]) do
139
+ spec = {Math::Arithmetic => [:inc],
140
+ Math => [:identity,
141
+ {:Statistics => [:avg,
142
+ {:Foo => [:blah, :quux]}]}]}
143
+ process_spec(spec).should == [[Math::Arithmetic, :inc],
144
+ [Math, :identity],
145
+ [Math::Statistics, :avg],
146
+ [Math::Statistics::Foo, :blah],
147
+ [Math::Statistics::Foo, :quux]]
148
+ end
149
+ end
71
150
  end
72
151
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rns
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-06 00:00:00.000000000 Z
12
+ date: 2012-05-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec