dunder 0.1.1 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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"