dunder 0.1.0 → 0.1.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/Rakefile +7 -1
- data/Readme.md +72 -3
- data/VERSION +1 -1
- data/dunder.gemspec +74 -0
- data/lib/dunder.rb +13 -19
- data/test/test_dunder.rb +10 -3
- metadata +12 -4
data/Rakefile
CHANGED
@@ -16,7 +16,13 @@ Jeweler::Tasks.new do |gem|
|
|
16
16
|
gem.homepage = "http://github.com/Fonsan/dunder"
|
17
17
|
gem.license = "MIT"
|
18
18
|
gem.summary = %Q{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}
|
19
|
-
gem.description = %Q{
|
19
|
+
gem.description = %Q{For tasks that can be started early and evaluated late.
|
20
|
+
|
21
|
+
Typically one might want start multiple heavy tasks concurrent.
|
22
|
+
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.
|
23
|
+
|
24
|
+
Dunder is a simple way of abstracting this:
|
25
|
+
you simply pass a block to Dunder.load with the expected class as the argument}
|
20
26
|
gem.email = "fonsan@gmail.com"
|
21
27
|
gem.authors = ["Fonsan"]
|
22
28
|
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
data/Readme.md
CHANGED
@@ -5,19 +5,88 @@ Heavily inspired by Adam Sandersons [post](http://endofline.wordpress.com/2011/0
|
|
5
5
|
|
6
6
|
Dunder
|
7
7
|
=========================
|
8
|
+
For tasks that can be started early and evaluated late.
|
8
9
|
|
10
|
+
Typically one might want start multiple heavy tasks concurrent.
|
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
|
+
|
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
|
9
15
|
|
10
16
|
Usage
|
11
|
-
|
12
|
-
|
17
|
+
|
18
|
+
lazy_foo = Dunder.load(String) {
|
13
19
|
# Simulate heavy IO
|
14
20
|
sleep 2
|
15
21
|
"bar"
|
16
22
|
}
|
23
|
+
|
24
|
+
|
25
|
+
lazy_b = Dunder.load(String) {
|
26
|
+
# Simulate heavy IO
|
27
|
+
sleep 2
|
28
|
+
"bar"
|
29
|
+
}
|
30
|
+
|
17
31
|
puts lazy_bar
|
32
|
+
puts lazy_foo
|
33
|
+
# Will finish after 2 seconds
|
34
|
+
|
35
|
+
worth mentioning is that if you access the variable in someway before that it will block earlier
|
36
|
+
ex
|
37
|
+
lazy_array = Dunder.load(Array) do
|
38
|
+
sleep 1
|
39
|
+
[1,2,3]
|
40
|
+
end
|
41
|
+
puts lazy_array.length # <- will block here until the above sleep is done
|
42
|
+
sleep 1 # other heavy stuff
|
43
|
+
puts lazy_array # <- will be printed after 2 seconds
|
44
|
+
|
45
|
+
changing the order will fix this though
|
46
|
+
|
47
|
+
lazy_array = Dunder.load(Array) do
|
48
|
+
sleep 1
|
49
|
+
[1,2,3]
|
50
|
+
end
|
51
|
+
sleep 1 # other heavy stuff
|
52
|
+
puts lazy_array.length # <- will block here until the above sleep in the block is done
|
53
|
+
puts lazy_array # <- will be printed after 1 second
|
54
|
+
|
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
|
+
|
63
|
+
Rails
|
64
|
+
|
65
|
+
@lazy_posts = Dunder.load(Array) do
|
66
|
+
Post.all
|
67
|
+
end
|
68
|
+
@lazy_users = Dunder.load(Array) do
|
69
|
+
User.all
|
70
|
+
end
|
71
|
+
|
72
|
+
and then later in views
|
73
|
+
|
74
|
+
<%= @lazyposts.each do %> <- this will block until the posts have been loaded
|
75
|
+
...
|
76
|
+
<% end %>
|
77
|
+
|
78
|
+
|
79
|
+
Known problems
|
80
|
+
|
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
|
86
|
+
|
18
87
|
Install
|
19
88
|
=======
|
20
|
-
gem install
|
89
|
+
gem install dunder
|
21
90
|
|
22
91
|
|
23
92
|
(The MIT License)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.1
|
data/dunder.gemspec
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{dunder}
|
8
|
+
s.version = "0.1.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Fonsan"]
|
12
|
+
s.date = %q{2011-01-26}
|
13
|
+
s.description = %q{For tasks that can be started early and evaluated late.
|
14
|
+
|
15
|
+
Typically one might want start multiple heavy tasks concurrent.
|
16
|
+
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.
|
17
|
+
|
18
|
+
Dunder is a simple way of abstracting this:
|
19
|
+
you simply pass a block to Dunder.load with the expected class as the argument}
|
20
|
+
s.email = %q{fonsan@gmail.com}
|
21
|
+
s.extra_rdoc_files = [
|
22
|
+
"LICENSE.txt"
|
23
|
+
]
|
24
|
+
s.files = [
|
25
|
+
"Gemfile",
|
26
|
+
"Gemfile.lock",
|
27
|
+
"LICENSE.txt",
|
28
|
+
"Rakefile",
|
29
|
+
"Readme.md",
|
30
|
+
"VERSION",
|
31
|
+
"dunder.gemspec",
|
32
|
+
"lib/dunder.rb",
|
33
|
+
"test/helper.rb",
|
34
|
+
"test/test_dunder.rb"
|
35
|
+
]
|
36
|
+
s.homepage = %q{http://github.com/Fonsan/dunder}
|
37
|
+
s.licenses = ["MIT"]
|
38
|
+
s.require_paths = ["lib"]
|
39
|
+
s.rubygems_version = %q{1.3.7}
|
40
|
+
s.summary = %q{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}
|
41
|
+
s.test_files = [
|
42
|
+
"test/helper.rb",
|
43
|
+
"test/test_dunder.rb"
|
44
|
+
]
|
45
|
+
|
46
|
+
if s.respond_to? :specification_version then
|
47
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
48
|
+
s.specification_version = 3
|
49
|
+
|
50
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
51
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 3.0.3"])
|
52
|
+
s.add_runtime_dependency(%q<activerecord>, [">= 3.0.3"])
|
53
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
54
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
55
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
56
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
57
|
+
else
|
58
|
+
s.add_dependency(%q<activesupport>, [">= 3.0.3"])
|
59
|
+
s.add_dependency(%q<activerecord>, [">= 3.0.3"])
|
60
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
61
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
62
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
63
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
64
|
+
end
|
65
|
+
else
|
66
|
+
s.add_dependency(%q<activesupport>, [">= 3.0.3"])
|
67
|
+
s.add_dependency(%q<activerecord>, [">= 3.0.3"])
|
68
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
69
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
70
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
71
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
data/lib/dunder.rb
CHANGED
@@ -3,6 +3,7 @@ require 'delegate'
|
|
3
3
|
|
4
4
|
class FutureArray < DelegateClass(Array )
|
5
5
|
def initialize(&block)
|
6
|
+
super(Array.new)
|
6
7
|
@_thread = Thread.start(&block)
|
7
8
|
end
|
8
9
|
|
@@ -12,6 +13,7 @@ class FutureArray < DelegateClass(Array )
|
|
12
13
|
end
|
13
14
|
end
|
14
15
|
|
16
|
+
|
15
17
|
class Dunder
|
16
18
|
|
17
19
|
def self.create_lazy_class(klass,instance = nil)
|
@@ -26,16 +28,23 @@ class Dunder
|
|
26
28
|
end
|
27
29
|
|
28
30
|
def __getobj__
|
29
|
-
|
30
|
-
|
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
|
31
40
|
end
|
41
|
+
|
32
42
|
end
|
33
43
|
instance ||= klass.new
|
34
|
-
|
35
44
|
def c.lazy_instance
|
36
45
|
instance
|
37
46
|
end
|
38
|
-
|
47
|
+
|
39
48
|
c
|
40
49
|
end
|
41
50
|
|
@@ -65,20 +74,5 @@ class Dunder
|
|
65
74
|
lazy_class.new(&block)
|
66
75
|
end
|
67
76
|
end
|
68
|
-
=begin
|
69
77
|
|
70
|
-
puts Dunder.load(String) {
|
71
|
-
"hello"
|
72
|
-
}
|
73
|
-
|
74
|
-
puts Dunder.load(Integer) {
|
75
|
-
1
|
76
|
-
}
|
77
|
-
|
78
|
-
puts Dunder.load(String) {
|
79
|
-
#Slow
|
80
|
-
sleep 2
|
81
|
-
"fubar"
|
82
|
-
}
|
83
78
|
|
84
|
-
=end
|
data/test/test_dunder.rb
CHANGED
@@ -2,8 +2,15 @@ require 'helper'
|
|
2
2
|
|
3
3
|
class TestDunder < Test::Unit::TestCase
|
4
4
|
should "have some simple testing" do
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
|
6
|
+
b = "bar"
|
7
|
+
|
8
|
+
lazy_b = Dunder.load(String) {
|
9
|
+
"bar"
|
10
|
+
}
|
11
|
+
|
12
|
+
assert_equal b,lazy_b
|
13
|
+
puts lazy_b.class
|
14
|
+
assert_equal b.class, lazy_b.class
|
8
15
|
end
|
9
16
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 1
|
9
|
+
version: 0.1.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Fonsan
|
@@ -103,7 +103,14 @@ dependencies:
|
|
103
103
|
type: :development
|
104
104
|
prerelease: false
|
105
105
|
version_requirements: *id006
|
106
|
-
description:
|
106
|
+
description: |-
|
107
|
+
For tasks that can be started early and evaluated late.
|
108
|
+
|
109
|
+
Typically one might want start multiple heavy tasks concurrent.
|
110
|
+
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.
|
111
|
+
|
112
|
+
Dunder is a simple way of abstracting this:
|
113
|
+
you simply pass a block to Dunder.load with the expected class as the argument
|
107
114
|
email: fonsan@gmail.com
|
108
115
|
executables: []
|
109
116
|
|
@@ -118,6 +125,7 @@ files:
|
|
118
125
|
- Rakefile
|
119
126
|
- Readme.md
|
120
127
|
- VERSION
|
128
|
+
- dunder.gemspec
|
121
129
|
- lib/dunder.rb
|
122
130
|
- test/helper.rb
|
123
131
|
- test/test_dunder.rb
|
@@ -135,7 +143,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
135
143
|
requirements:
|
136
144
|
- - ">="
|
137
145
|
- !ruby/object:Gem::Version
|
138
|
-
hash:
|
146
|
+
hash: 2997372027129916411
|
139
147
|
segments:
|
140
148
|
- 0
|
141
149
|
version: "0"
|