mattmatt-threadlocal-attr-accessor 0.0.2
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 +29 -0
- data/Rakefile +32 -0
- data/VERSION.yml +4 -0
- data/lib/core_ext/module.rb +28 -0
- data/test/attr_accessor_test.rb +138 -0
- data/test/test_helper.rb +5 -0
- metadata +60 -0
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
Thread-local attr_accessor
|
2
|
+
========
|
3
|
+
|
4
|
+
Think attr_accessor, only thread-local. Figures, huh?
|
5
|
+
|
6
|
+
require 'threadsafe-attr-accessor'
|
7
|
+
|
8
|
+
class Person
|
9
|
+
tl_attr_accessor :name
|
10
|
+
tl_attr_writer :spouse
|
11
|
+
tl_attr_reader :fullname
|
12
|
+
end
|
13
|
+
|
14
|
+
Yeah, I know the examples above probably aren't good
|
15
|
+
candidates for thread-local attribute accessors, but
|
16
|
+
you get the gist.
|
17
|
+
|
18
|
+
Works for classes too:
|
19
|
+
|
20
|
+
class Person
|
21
|
+
tl_cattr_accessor :connection
|
22
|
+
end
|
23
|
+
|
24
|
+
License
|
25
|
+
=======
|
26
|
+
|
27
|
+
(c) 2009 Mathias Meyer
|
28
|
+
|
29
|
+
MIT Baby!
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |s|
|
8
|
+
s.name = 'threadlocal-attr-accessor'
|
9
|
+
s.summary = 'Think attr_accessor, only thread-local. Figures, huh?'
|
10
|
+
s.email = 'meyer@paperplanes.de'
|
11
|
+
s.homepage = 'http://github.com/mattmatt/threadlocal-attr-accessor'
|
12
|
+
s.authors = ["Mathias Meyer"]
|
13
|
+
s.files = FileList["[A-Z]*", "{lib,test}/**/*"]
|
14
|
+
end
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "Default Task"
|
20
|
+
task :default => ["test"]
|
21
|
+
|
22
|
+
desc "Runs the unit tests"
|
23
|
+
task :test => "test:unit"
|
24
|
+
|
25
|
+
namespace :test do
|
26
|
+
desc "Unit tests"
|
27
|
+
Rake::TestTask.new(:unit) do |t|
|
28
|
+
t.libs << 'test'
|
29
|
+
t.pattern = "test/*_test.rb"
|
30
|
+
t.verbose = true
|
31
|
+
end
|
32
|
+
end
|
data/VERSION.yml
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
class Module
|
2
|
+
def tl_attr_accessor(*names)
|
3
|
+
tl_attr_reader(*names)
|
4
|
+
tl_attr_writer(*names)
|
5
|
+
end
|
6
|
+
|
7
|
+
def tl_attr_reader(*names)
|
8
|
+
names.each do |name|
|
9
|
+
define_method(name) do
|
10
|
+
Thread.current["#{self.class.name.downcase}_#{object_id}_#{name.to_s}"]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def tl_attr_writer(*names)
|
16
|
+
names.each do |name|
|
17
|
+
define_method("#{name}=".to_sym) do |new_value|
|
18
|
+
Thread.current["#{self.class.name.downcase}_#{object_id}_#{name.to_s}"] = new_value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def tl_attr(name, writable = false)
|
24
|
+
tl_attr_reader(name)
|
25
|
+
|
26
|
+
tl_attr_writer(name) if writable
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Person
|
4
|
+
tl_attr_accessor :connection
|
5
|
+
tl_attr_reader :owner
|
6
|
+
tl_attr_writer :job
|
7
|
+
|
8
|
+
tl_attr :name, true
|
9
|
+
tl_attr :firstname
|
10
|
+
tl_attr :nickname, false
|
11
|
+
|
12
|
+
tl_attr_accessor :other_connection, :real_connection
|
13
|
+
tl_attr_reader :spouse, :children
|
14
|
+
tl_attr_writer :occupation, :hobbies
|
15
|
+
end
|
16
|
+
|
17
|
+
class AttrAccessorTest < Test::Unit::TestCase
|
18
|
+
context "with a person instance" do
|
19
|
+
setup do
|
20
|
+
@person = Person.new
|
21
|
+
end
|
22
|
+
|
23
|
+
context "and a connection" do
|
24
|
+
setup do
|
25
|
+
@person.connection = :connection
|
26
|
+
end
|
27
|
+
|
28
|
+
should "keep the connection in a thread local variable" do
|
29
|
+
assert_not_nil Thread.current["person_#{@person.object_id}_connection"]
|
30
|
+
end
|
31
|
+
|
32
|
+
should "be nil in a different thread" do
|
33
|
+
person = @person
|
34
|
+
t = Thread.new {Thread.current[:result] = person.connection}
|
35
|
+
t.join
|
36
|
+
assert_nil t[:result]
|
37
|
+
assert_not_nil person.connection
|
38
|
+
end
|
39
|
+
|
40
|
+
should "store different values for different threads" do
|
41
|
+
person = @person
|
42
|
+
t = Thread.new do
|
43
|
+
person.connection = :other_connection
|
44
|
+
Thread.current[:result] = person.connection
|
45
|
+
end
|
46
|
+
t.join
|
47
|
+
assert_equal :other_connection, t[:result]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "and an owner" do
|
52
|
+
setup do
|
53
|
+
Thread.current["person_#{@person.object_id}_owner"] = :god
|
54
|
+
end
|
55
|
+
|
56
|
+
should "return the value from thread local" do
|
57
|
+
assert_equal :god, @person.owner
|
58
|
+
end
|
59
|
+
|
60
|
+
should "be nil in a different thread" do
|
61
|
+
person = @person
|
62
|
+
t = Thread.new do
|
63
|
+
Thread.current[:result] = person.owner
|
64
|
+
end
|
65
|
+
t.join
|
66
|
+
assert_nil t[:result]
|
67
|
+
assert_equal :god, person.owner
|
68
|
+
end
|
69
|
+
|
70
|
+
should "not have a setter defined" do
|
71
|
+
assert !@person.respond_to?("owner=")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context "and a job" do
|
76
|
+
setup do
|
77
|
+
@person.job = :janitor
|
78
|
+
end
|
79
|
+
|
80
|
+
should "store the job in a thread local" do
|
81
|
+
assert_equal :janitor, Thread.current["person_#{@person.object_id}_job"]
|
82
|
+
end
|
83
|
+
|
84
|
+
should "not have a getter" do
|
85
|
+
assert !@person.respond_to?(:job)
|
86
|
+
end
|
87
|
+
|
88
|
+
should "be not overwrite from a different" do
|
89
|
+
person = @person
|
90
|
+
t = Thread.new do
|
91
|
+
person.job = :ceo
|
92
|
+
end
|
93
|
+
t.join
|
94
|
+
assert_equal :janitor, Thread.current["person_#{@person.object_id}_job"]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "with multiple variable names" do
|
99
|
+
should "create accessors for all variable names" do
|
100
|
+
assert @person.respond_to?(:other_connection)
|
101
|
+
assert @person.respond_to?(:real_connection)
|
102
|
+
assert @person.respond_to?(:real_connection=)
|
103
|
+
assert @person.respond_to?(:other_connection=)
|
104
|
+
end
|
105
|
+
|
106
|
+
should "create only read-only accessors for all variable names" do
|
107
|
+
assert @person.respond_to?(:spouse)
|
108
|
+
assert @person.respond_to?(:children)
|
109
|
+
assert !@person.respond_to?(:spouse=)
|
110
|
+
assert !@person.respond_to?(:children=)
|
111
|
+
end
|
112
|
+
|
113
|
+
should "create only write accessors for all variable names" do
|
114
|
+
assert !@person.respond_to?(:occupation)
|
115
|
+
assert !@person.respond_to?(:hobbies)
|
116
|
+
assert @person.respond_to?(:occupation=)
|
117
|
+
assert @person.respond_to?(:hobbies=)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context "with attr" do
|
122
|
+
should "create a getter and no setter by default" do
|
123
|
+
assert @person.respond_to?(:firstname)
|
124
|
+
assert !@person.respond_to?(:firstname=)
|
125
|
+
end
|
126
|
+
|
127
|
+
should "create a getter and setter with second parameter true" do
|
128
|
+
assert @person.respond_to?(:name)
|
129
|
+
assert @person.respond_to?(:name=)
|
130
|
+
end
|
131
|
+
|
132
|
+
should "create only getter when second parameter false" do
|
133
|
+
assert @person.respond_to?(:nickname)
|
134
|
+
assert !@person.respond_to?(:nickname=)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mattmatt-threadlocal-attr-accessor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mathias Meyer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-02-26 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: meyer@paperplanes.de
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- Rakefile
|
26
|
+
- README.md
|
27
|
+
- VERSION.yml
|
28
|
+
- lib/core_ext
|
29
|
+
- lib/core_ext/module.rb
|
30
|
+
- test/attr_accessor_test.rb
|
31
|
+
- test/test_helper.rb
|
32
|
+
has_rdoc: true
|
33
|
+
homepage: http://github.com/mattmatt/threadlocal-attr-accessor
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options:
|
36
|
+
- --inline-source
|
37
|
+
- --charset=UTF-8
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: "0"
|
45
|
+
version:
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: "0"
|
51
|
+
version:
|
52
|
+
requirements: []
|
53
|
+
|
54
|
+
rubyforge_project:
|
55
|
+
rubygems_version: 1.2.0
|
56
|
+
signing_key:
|
57
|
+
specification_version: 2
|
58
|
+
summary: Think attr_accessor, only thread-local. Figures, huh?
|
59
|
+
test_files: []
|
60
|
+
|