dunder 0.1.1 → 0.2.1

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.md CHANGED
@@ -1,4 +1,4 @@
1
- A simple way of doing heavy work in a background process and when you really need the object it will block until it is done
1
+ A simple way of doing heavy work in a background process and blocking until done when you really need the object.
2
2
 
3
3
  Preloading using the [proxy pattern](http://sourcemaking.com/design_patterns/proxy)
4
4
  Heavily inspired by Adam Sandersons [post](http://endofline.wordpress.com/2011/01/18/ruby-standard-library-delegator/)
@@ -11,30 +11,55 @@ Typically one might want start multiple heavy tasks concurrent.
11
11
  This is already solvable with threads or the [reactor-pattern](http://rubyeventmachine.com/) but setting this up could be cumbersome or require direct interactions with threads ex.
12
12
 
13
13
  Dunder is a simple way of abstracting this:
14
- you simply pass a block to Dunder.load with the expected class as the argument
14
+ you simply pass a block to Dunder.load and Dunder will execute this in a thread behind the scenes.
15
+ When later accessing the lazy_object will block until the thread is done and has returned or if the thread is done returns the value
16
+
17
+ The implementation itself relies only on the ruby standard library and is below 50 lines of code
15
18
 
16
19
  Usage
17
20
 
18
- lazy_foo = Dunder.load(String) {
21
+ lazy_object = Dunder.load {
22
+ # heavy stuff
23
+ value
24
+ }
25
+
26
+ or through dunder_load
27
+
28
+ lazy_sorted_articles = @articles.dunder_load.sort_by do |a|
29
+ a.title
30
+ end
31
+
32
+ lazy_sorted_array = array.dunder_load.sort
33
+
34
+ lazy_obj = obj.dunder_load.do_something_heavy(a,b,c) {
35
+ #maybe something other heavy here
36
+ }
37
+
38
+ Read more further down
39
+
40
+ lazy_foo = Dunder.load {
19
41
  # Simulate heavy IO
20
42
  sleep 2
21
- "bar"
43
+ "foo"
22
44
  }
23
45
 
24
-
25
- lazy_b = Dunder.load(String) {
46
+ lazy_bar = Dunder.load {
26
47
  # Simulate heavy IO
27
48
  sleep 2
28
49
  "bar"
29
50
  }
30
51
 
31
- puts lazy_bar
32
- puts lazy_foo
52
+ # Do something other heavy
53
+
54
+ puts lazy_bar # => "bar"
55
+ puts lazy_bar.class # => String
56
+ puts lazy_foo # => "foo"
57
+ puts lazy_foo.class # => String
33
58
  # Will finish after 2 seconds
34
59
 
35
60
  worth mentioning is that if you access the variable in someway before that it will block earlier
36
61
  ex
37
- lazy_array = Dunder.load(Array) do
62
+ lazy_array = Dunder.load do
38
63
  sleep 1
39
64
  [1,2,3]
40
65
  end
@@ -42,9 +67,9 @@ ex
42
67
  sleep 1 # other heavy stuff
43
68
  puts lazy_array # <- will be printed after 2 seconds
44
69
 
45
- changing the order will fix this though
70
+ changing the order of the statements will fix this though
46
71
 
47
- lazy_array = Dunder.load(Array) do
72
+ lazy_array = Dunder.load do
48
73
  sleep 1
49
74
  [1,2,3]
50
75
  end
@@ -52,20 +77,14 @@ changing the order will fix this though
52
77
  puts lazy_array.length # <- will block here until the above sleep in the block is done
53
78
  puts lazy_array # <- will be printed after 1 second
54
79
 
55
- API
56
- Dunder.load(Klass,instance = nil) {
57
- #things to do
58
- value
59
- }
60
- Klass must be the class of value
61
- instance, During the process Dunder will call Klass.new if your class has a mandatory argument in initialize (the constructor) you could create a dummy instance yourself or you could set the return type to Array and return [value] and then use Dunder.load(Array) do [value] end.first
62
80
 
63
81
  Rails
82
+ ====================
64
83
 
65
- @lazy_posts = Dunder.load(Array) do
84
+ @lazy_posts = Dunder.load do
66
85
  Post.all
67
86
  end
68
- @lazy_users = Dunder.load(Array) do
87
+ @lazy_users = Dunder.load do
69
88
  User.all
70
89
  end
71
90
 
@@ -78,11 +97,7 @@ and then later in views
78
97
 
79
98
  Known problems
80
99
 
81
- it works with most types but has only been tested with 1.9.2
82
- Integer fails with
83
- NotImplementedError: super from singleton method that is defined to multiple classes is not supported;
84
- this will be fixed in 1.9.3 or later
85
- Or a SystemStackError: stack level too deep
100
+ Has only been tested with 1.9.2
86
101
 
87
102
  Install
88
103
  =======
@@ -91,7 +106,7 @@ Install
91
106
 
92
107
  (The MIT License)
93
108
 
94
- Copyright (c) 2001-2006 Erik Fonselius
109
+ Copyright (c) 2011 Erik Fonselius
95
110
 
96
111
  Permission is hereby granted, free of charge, to any person obtaining
97
112
  a copy of this software and associated documentation files (the
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.1
data/dunder.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{dunder}
8
- s.version = "0.1.1"
8
+ s.version = "0.2.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Fonsan"]
12
- s.date = %q{2011-01-26}
12
+ s.date = %q{2011-01-28}
13
13
  s.description = %q{For tasks that can be started early and evaluated late.
14
14
 
15
15
  Typically one might want start multiple heavy tasks concurrent.
data/lib/dunder.rb CHANGED
@@ -1,78 +1,50 @@
1
- # From http://endofline.wordpress.com/2011/01/18/ruby-standard-library-delegator/
2
1
  require 'delegate'
3
-
4
- class FutureArray < DelegateClass(Array )
5
- def initialize(&block)
6
- super(Array.new)
7
- @_thread = Thread.start(&block)
8
- end
9
-
10
- def __getobj__
11
- __setobj__(@_thread.value) if @_thread.alive?
12
- super
13
- end
14
- end
15
-
16
-
17
2
  class Dunder
18
-
19
- def self.create_lazy_class(klass,instance = nil)
20
- c = Class.new(DelegateClass(klass)) do
21
- def lazy_instance
22
- # Will be filled in later
23
- end
24
-
25
- def initialize(&block)
26
- @_thread = Thread.start(&block)
27
- super(self.lazy_instance)
28
- end
29
-
30
- def __getobj__
31
- result = @_thread.value
32
- __setobj__(result) if @_thread.alive?
33
-
34
- instance_eval do
35
- def class
36
- __getobj__.class
37
- end
38
- end
39
- result
40
- end
41
-
42
- end
43
- instance ||= klass.new
44
- def c.lazy_instance
45
- instance
3
+ class Future < SimpleDelegator
4
+ def initialize(&block)
5
+ @_thread = Thread.start(&block)
46
6
  end
47
7
 
48
- c
49
- end
50
-
51
- def self.create_lazy_class!(klass, instance = nil)
52
- @@lazy_classes[klass] = create_lazy_class(klass,instance)
8
+ def __getobj__
9
+ __setobj__(@_thread.value) if @_thread.alive?
10
+ super
11
+ end
12
+
13
+ def class
14
+ __getobj__.class
15
+ end
53
16
  end
54
17
 
55
- @@lazy_classes = Hash.new do |hash,key|
56
- hash[key] = create_lazy_class(key)
18
+ def self.load(&block)
19
+ Future.new(&block)
57
20
  end
58
21
 
59
- # All standard klasses with a constructor having mandatory arguments
60
- # More to add
61
- @@default_instances = {
62
- Integer => 0
63
- }
64
-
65
- @@default_instances.each do |k,v|
66
- create_lazy_class!(k,v)
22
+ class Dispacter < SimpleDelegator
23
+ def initialize(object)
24
+ @_dunder_obj = object
25
+ end
26
+
27
+ def class
28
+ @_dunder_obj.class
29
+ end
30
+
31
+ def method_missing(method_sym, *arguments,&block)
32
+ Dunder.load do
33
+ @_dunder_obj.send(method_sym, *arguments,&block)
34
+ end
35
+ end
67
36
  end
68
-
69
- def self.load(klass,instance = nil,&block)
70
- lazy_class = !@@lazy_classes.key?(klass) && instance ?
71
- @@lazy_classes[klass] = create_lazy_class(klass,instance)
72
- :
73
- @@lazy_classes[klass]
74
- lazy_class.new(&block)
37
+ end
38
+
39
+ class Object
40
+ def dunder_load
41
+ Dunder::Dispacter.new(self)
75
42
  end
76
43
  end
77
44
 
78
45
 
46
+
47
+
48
+
49
+
50
+
data/test/test_dunder.rb CHANGED
@@ -1,16 +1,38 @@
1
1
  require 'helper'
2
-
2
+ require 'timeout'
3
3
  class TestDunder < Test::Unit::TestCase
4
4
  should "have some simple testing" do
5
-
6
5
  b = "bar"
7
-
8
- lazy_b = Dunder.load(String) {
9
- "bar"
10
- }
11
-
6
+ lazy_b = nil
7
+ assert_nothing_raised do
8
+ Timeout::timeout(0.5) do
9
+
10
+ lazy_b = Dunder.load {
11
+ sleep 1
12
+ "bar"
13
+ }
14
+ end
15
+ end
12
16
  assert_equal b,lazy_b
13
- puts lazy_b.class
14
17
  assert_equal b.class, lazy_b.class
15
18
  end
19
+
20
+ should "respond to dunder_load" do
21
+ assert Object.public_instance_methods.index(:dunder_load)
22
+ b = "bar"
23
+ b.instance_eval do
24
+ def something_heavy
25
+ yield
26
+ self
27
+ end
28
+ end
29
+ res = nil
30
+ assert_nothing_raised do
31
+ Timeout::timeout(0.5) do
32
+ res = b.dunder_load.something_heavy { sleep 1 }
33
+ end
34
+ end
35
+ assert_equal b,res
36
+ assert_equal b.class,res.class
37
+ end
16
38
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
+ - 2
7
8
  - 1
8
- - 1
9
- version: 0.1.1
9
+ version: 0.2.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Fonsan
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-01-26 00:00:00 +01:00
17
+ date: 2011-01-28 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -143,7 +143,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
143
143
  requirements:
144
144
  - - ">="
145
145
  - !ruby/object:Gem::Version
146
- hash: 2997372027129916411
146
+ hash: 1083880034677177238
147
147
  segments:
148
148
  - 0
149
149
  version: "0"