rubysl-singleton 1.0.0
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/LICENSE +25 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/rubysl/singleton.rb +2 -0
- data/lib/rubysl/singleton/singleton.rb +313 -0
- data/lib/rubysl/singleton/version.rb +5 -0
- data/lib/singleton.rb +1 -0
- data/rubysl-singleton.gemspec +23 -0
- data/spec/allocate_spec.rb +7 -0
- data/spec/clone_spec.rb +7 -0
- data/spec/dump_spec.rb +13 -0
- data/spec/dup_spec.rb +7 -0
- data/spec/fixtures/classes.rb +18 -0
- data/spec/instance_spec.rb +29 -0
- data/spec/instantiate_spec.rb +20 -0
- data/spec/load_spec.rb +22 -0
- data/spec/new_spec.rb +7 -0
- metadata +130 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a68b8b94eadd7fe3c8e3f30ff58b1fb1d0303481
|
4
|
+
data.tar.gz: 4f0af342cda53ce98431f81227ea3fdced184877
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 04dfdf1c1cb3776b10f8100c2d650c3aaf3d58d7224460ce800ebd3eff49d8cc251510a07367b80645617e85acd282953433fbb10d8580327e59774d6a6a085d
|
7
|
+
data.tar.gz: add0ca325e06b7e6cb6c5d46d016a7a7e7175df4db5e5e96ade43f4bfe411311c867902d8ad58bf495a84f605aaf8891bbb95c4b86644b36d4d7727e3bf0304d
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
Copyright (c) 2013, Brian Shirai
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
11
|
+
and/or other materials provided with the distribution.
|
12
|
+
3. Neither the name of the library nor the names of its contributors may be
|
13
|
+
used to endorse or promote products derived from this software without
|
14
|
+
specific prior written permission.
|
15
|
+
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
17
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
18
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
19
|
+
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT,
|
20
|
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
21
|
+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
22
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
23
|
+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
24
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
25
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Rubysl::Singleton
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'rubysl-singleton'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install rubysl-singleton
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,313 @@
|
|
1
|
+
# The Singleton module implements the Singleton pattern.
|
2
|
+
#
|
3
|
+
# Usage:
|
4
|
+
# class Klass
|
5
|
+
# include Singleton
|
6
|
+
# # ...
|
7
|
+
# end
|
8
|
+
#
|
9
|
+
# * this ensures that only one instance of Klass lets call it
|
10
|
+
# ``the instance'' can be created.
|
11
|
+
#
|
12
|
+
# a,b = Klass.instance, Klass.instance
|
13
|
+
# a == b # => true
|
14
|
+
# Klass.new # NoMethodError - new is private ...
|
15
|
+
#
|
16
|
+
# * ``The instance'' is created at instantiation time, in other
|
17
|
+
# words the first call of Klass.instance(), thus
|
18
|
+
#
|
19
|
+
# class OtherKlass
|
20
|
+
# include Singleton
|
21
|
+
# # ...
|
22
|
+
# end
|
23
|
+
# ObjectSpace.each_object(OtherKlass){} # => 0.
|
24
|
+
#
|
25
|
+
# * This behavior is preserved under inheritance and cloning.
|
26
|
+
#
|
27
|
+
#
|
28
|
+
#
|
29
|
+
# This is achieved by marking
|
30
|
+
# * Klass.new and Klass.allocate - as private
|
31
|
+
#
|
32
|
+
# Providing (or modifying) the class methods
|
33
|
+
# * Klass.inherited(sub_klass) and Klass.clone() -
|
34
|
+
# to ensure that the Singleton pattern is properly
|
35
|
+
# inherited and cloned.
|
36
|
+
#
|
37
|
+
# * Klass.instance() - returning ``the instance''. After a
|
38
|
+
# successful self modifying (normally the first) call the
|
39
|
+
# method body is a simple:
|
40
|
+
#
|
41
|
+
# def Klass.instance()
|
42
|
+
# return @singleton__instance__
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# * Klass._load(str) - calling Klass.instance()
|
46
|
+
#
|
47
|
+
# * Klass._instantiate?() - returning ``the instance'' or
|
48
|
+
# nil. This hook method puts a second (or nth) thread calling
|
49
|
+
# Klass.instance() on a waiting loop. The return value
|
50
|
+
# signifies the successful completion or premature termination
|
51
|
+
# of the first, or more generally, current "instantiation thread".
|
52
|
+
#
|
53
|
+
#
|
54
|
+
# The instance method of Singleton are
|
55
|
+
# * clone and dup - raising TypeErrors to prevent cloning or duping
|
56
|
+
#
|
57
|
+
# * _dump(depth) - returning the empty string. Marshalling strips
|
58
|
+
# by default all state information, e.g. instance variables and
|
59
|
+
# taint state, from ``the instance''. Providing custom _load(str)
|
60
|
+
# and _dump(depth) hooks allows the (partially) resurrections of
|
61
|
+
# a previous state of ``the instance''.
|
62
|
+
|
63
|
+
require 'thread'
|
64
|
+
|
65
|
+
module Singleton
|
66
|
+
# disable build-in copying methods
|
67
|
+
def clone
|
68
|
+
raise TypeError, "can't clone instance of singleton #{self.class}"
|
69
|
+
end
|
70
|
+
def dup
|
71
|
+
raise TypeError, "can't dup instance of singleton #{self.class}"
|
72
|
+
end
|
73
|
+
|
74
|
+
# default marshalling strategy
|
75
|
+
def _dump(depth = -1)
|
76
|
+
''
|
77
|
+
end
|
78
|
+
|
79
|
+
module SingletonClassMethods
|
80
|
+
# properly clone the Singleton pattern - did you know
|
81
|
+
# that duping doesn't copy class methods?
|
82
|
+
def clone
|
83
|
+
Singleton.__init__(super)
|
84
|
+
end
|
85
|
+
|
86
|
+
def _load(str)
|
87
|
+
instance
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
# ensure that the Singleton pattern is properly inherited
|
93
|
+
def inherited(sub_klass)
|
94
|
+
super
|
95
|
+
Singleton.__init__(sub_klass)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class << Singleton
|
100
|
+
def __init__(klass)
|
101
|
+
klass.instance_eval {
|
102
|
+
@singleton__instance__ = nil
|
103
|
+
@singleton__mutex__ = Mutex.new
|
104
|
+
}
|
105
|
+
def klass.instance
|
106
|
+
return @singleton__instance__ if @singleton__instance__
|
107
|
+
@singleton__mutex__.synchronize {
|
108
|
+
return @singleton__instance__ if @singleton__instance__
|
109
|
+
@singleton__instance__ = new()
|
110
|
+
}
|
111
|
+
@singleton__instance__
|
112
|
+
end
|
113
|
+
klass
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
# extending an object with Singleton is a bad idea
|
119
|
+
undef_method :extend_object
|
120
|
+
|
121
|
+
def append_features(mod)
|
122
|
+
# help out people counting on transitive mixins
|
123
|
+
unless mod.instance_of?(Class)
|
124
|
+
raise TypeError, "Inclusion of the OO-Singleton module in module #{mod}"
|
125
|
+
end
|
126
|
+
super
|
127
|
+
end
|
128
|
+
|
129
|
+
def included(klass)
|
130
|
+
super
|
131
|
+
klass.private_class_method :new, :allocate
|
132
|
+
klass.extend SingletonClassMethods
|
133
|
+
Singleton.__init__(klass)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
if __FILE__ == $0
|
141
|
+
|
142
|
+
def num_of_instances(klass)
|
143
|
+
"#{ObjectSpace.each_object(klass){}} #{klass} instance(s)"
|
144
|
+
end
|
145
|
+
|
146
|
+
# The basic and most important example.
|
147
|
+
|
148
|
+
class SomeSingletonClass
|
149
|
+
include Singleton
|
150
|
+
end
|
151
|
+
puts "There are #{num_of_instances(SomeSingletonClass)}"
|
152
|
+
|
153
|
+
a = SomeSingletonClass.instance
|
154
|
+
b = SomeSingletonClass.instance # a and b are same object
|
155
|
+
puts "basic test is #{a == b}"
|
156
|
+
|
157
|
+
begin
|
158
|
+
SomeSingletonClass.new
|
159
|
+
rescue NoMethodError => mes
|
160
|
+
puts mes
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
|
165
|
+
puts "\nThreaded example with exception and customized #_instantiate?() hook"; p
|
166
|
+
Thread.abort_on_exception = false
|
167
|
+
|
168
|
+
class Ups < SomeSingletonClass
|
169
|
+
def initialize
|
170
|
+
self.class.__sleep
|
171
|
+
puts "initialize called by thread ##{Thread.current[:i]}"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
class << Ups
|
176
|
+
def _instantiate?
|
177
|
+
@enter.push Thread.current[:i]
|
178
|
+
while false.equal?(@singleton__instance__)
|
179
|
+
@singleton__mutex__.unlock
|
180
|
+
sleep 0.08
|
181
|
+
@singleton__mutex__.lock
|
182
|
+
end
|
183
|
+
@leave.push Thread.current[:i]
|
184
|
+
@singleton__instance__
|
185
|
+
end
|
186
|
+
|
187
|
+
def __sleep
|
188
|
+
sleep(rand(0.08))
|
189
|
+
end
|
190
|
+
|
191
|
+
def new
|
192
|
+
begin
|
193
|
+
__sleep
|
194
|
+
raise "boom - thread ##{Thread.current[:i]} failed to create instance"
|
195
|
+
ensure
|
196
|
+
# simple flip-flop
|
197
|
+
class << self
|
198
|
+
remove_method :new
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def instantiate_all
|
204
|
+
@enter = []
|
205
|
+
@leave = []
|
206
|
+
1.upto(9) {|i|
|
207
|
+
Thread.new {
|
208
|
+
begin
|
209
|
+
Thread.current[:i] = i
|
210
|
+
__sleep
|
211
|
+
instance
|
212
|
+
rescue RuntimeError => mes
|
213
|
+
puts mes
|
214
|
+
end
|
215
|
+
}
|
216
|
+
}
|
217
|
+
puts "Before there were #{num_of_instances(self)}"
|
218
|
+
sleep 3
|
219
|
+
puts "Now there is #{num_of_instances(self)}"
|
220
|
+
puts "#{@enter.join '; '} was the order of threads entering the waiting loop"
|
221
|
+
puts "#{@leave.join '; '} was the order of threads leaving the waiting loop"
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
|
226
|
+
Ups.instantiate_all
|
227
|
+
# results in message like
|
228
|
+
# Before there were 0 Ups instance(s)
|
229
|
+
# boom - thread #6 failed to create instance
|
230
|
+
# initialize called by thread #3
|
231
|
+
# Now there is 1 Ups instance(s)
|
232
|
+
# 3; 2; 1; 8; 4; 7; 5 was the order of threads entering the waiting loop
|
233
|
+
# 3; 2; 1; 7; 4; 8; 5 was the order of threads leaving the waiting loop
|
234
|
+
|
235
|
+
|
236
|
+
puts "\nLets see if class level cloning really works"
|
237
|
+
Yup = Ups.clone
|
238
|
+
def Yup.new
|
239
|
+
begin
|
240
|
+
__sleep
|
241
|
+
raise "boom - thread ##{Thread.current[:i]} failed to create instance"
|
242
|
+
ensure
|
243
|
+
# simple flip-flop
|
244
|
+
class << self
|
245
|
+
remove_method :new
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
Yup.instantiate_all
|
250
|
+
|
251
|
+
|
252
|
+
puts "\n\n","Customized marshalling"
|
253
|
+
class A
|
254
|
+
include Singleton
|
255
|
+
attr_accessor :persist, :die
|
256
|
+
def _dump(depth)
|
257
|
+
# this strips the @die information from the instance
|
258
|
+
Marshal.dump(@persist,depth)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def A._load(str)
|
263
|
+
instance.persist = Marshal.load(str)
|
264
|
+
instance
|
265
|
+
end
|
266
|
+
|
267
|
+
a = A.instance
|
268
|
+
a.persist = ["persist"]
|
269
|
+
a.die = "die"
|
270
|
+
a.taint
|
271
|
+
|
272
|
+
stored_state = Marshal.dump(a)
|
273
|
+
# change state
|
274
|
+
a.persist = nil
|
275
|
+
a.die = nil
|
276
|
+
b = Marshal.load(stored_state)
|
277
|
+
p a == b # => true
|
278
|
+
p a.persist # => ["persist"]
|
279
|
+
p a.die # => nil
|
280
|
+
|
281
|
+
|
282
|
+
puts "\n\nSingleton with overridden default #inherited() hook"
|
283
|
+
class Up
|
284
|
+
end
|
285
|
+
def Up.inherited(sub_klass)
|
286
|
+
puts "#{sub_klass} subclasses #{self}"
|
287
|
+
end
|
288
|
+
|
289
|
+
|
290
|
+
class Middle < Up
|
291
|
+
include Singleton
|
292
|
+
end
|
293
|
+
|
294
|
+
class Down < Middle; end
|
295
|
+
|
296
|
+
puts "and basic \"Down test\" is #{Down.instance == Down.instance}\n
|
297
|
+
Various exceptions"
|
298
|
+
|
299
|
+
begin
|
300
|
+
module AModule
|
301
|
+
include Singleton
|
302
|
+
end
|
303
|
+
rescue TypeError => mes
|
304
|
+
puts mes #=> Inclusion of the OO-Singleton module in module AModule
|
305
|
+
end
|
306
|
+
|
307
|
+
begin
|
308
|
+
'aString'.extend Singleton
|
309
|
+
rescue NoMethodError => mes
|
310
|
+
puts mes #=> undefined method `extend_object' for Singleton:Module
|
311
|
+
end
|
312
|
+
|
313
|
+
end
|
data/lib/singleton.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "rubysl/singleton"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require './lib/rubysl/singleton/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = "rubysl-singleton"
|
6
|
+
spec.version = RubySL::Singleton::VERSION
|
7
|
+
spec.authors = ["Brian Shirai"]
|
8
|
+
spec.email = ["brixen@gmail.com"]
|
9
|
+
spec.description = %q{Ruby standard library singleton.}
|
10
|
+
spec.summary = %q{Ruby standard library singleton.}
|
11
|
+
spec.homepage = "https://github.com/rubysl/rubysl-singleton"
|
12
|
+
spec.license = "BSD"
|
13
|
+
|
14
|
+
spec.files = `git ls-files`.split($/)
|
15
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
16
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
17
|
+
spec.require_paths = ["lib"]
|
18
|
+
|
19
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
20
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
21
|
+
spec.add_development_dependency "mspec", "~> 1.5"
|
22
|
+
spec.add_development_dependency "rubysl-prettyprint", "~> 1.0"
|
23
|
+
end
|
data/spec/clone_spec.rb
ADDED
data/spec/dump_spec.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
2
|
+
|
3
|
+
describe "Singleton#_dump" do
|
4
|
+
|
5
|
+
it "returns an empty string" do
|
6
|
+
SingletonSpecs::MyClass.instance.send(:_dump).should == ""
|
7
|
+
end
|
8
|
+
|
9
|
+
it "returns an empty string from a singleton subclass" do
|
10
|
+
SingletonSpecs::MyClassChild.instance.send(:_dump).should == ""
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
data/spec/dup_spec.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module SingletonSpecs
|
4
|
+
class MyClass
|
5
|
+
attr_accessor :data
|
6
|
+
include Singleton
|
7
|
+
end
|
8
|
+
|
9
|
+
class NewSpec
|
10
|
+
include Singleton
|
11
|
+
end
|
12
|
+
|
13
|
+
class MyClassChild < MyClass
|
14
|
+
end
|
15
|
+
|
16
|
+
class NotInstantiated < MyClass
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
2
|
+
|
3
|
+
describe "Singleton.instance" do
|
4
|
+
it "returns an instance of the singleton class" do
|
5
|
+
SingletonSpecs::MyClass.instance.should be_kind_of(SingletonSpecs::MyClass)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "returns the same instance for multiple calls to instance" do
|
9
|
+
SingletonSpecs::MyClass.instance.should equal(SingletonSpecs::MyClass.instance)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "returns an instance of the singleton's subclasses" do
|
13
|
+
SingletonSpecs::MyClassChild.instance.should be_kind_of(SingletonSpecs::MyClassChild)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "returns the same instance for multiple class to instance on subclasses" do
|
17
|
+
SingletonSpecs::MyClassChild.instance.should equal(SingletonSpecs::MyClassChild.instance)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "returns an instance of the singleton's clone" do
|
21
|
+
klone = SingletonSpecs::MyClassChild.clone
|
22
|
+
klone.instance.should be_kind_of(klone)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "returns the same instance for multiple class to instance on clones" do
|
26
|
+
klone = SingletonSpecs::MyClassChild.clone
|
27
|
+
klone.instance.should equal(klone.instance)
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
2
|
+
|
3
|
+
describe "Singleton._instantiate?" do
|
4
|
+
|
5
|
+
it "is private" do
|
6
|
+
lambda { SingletonSpecs::MyClass._instantiate? }.should raise_error(NoMethodError)
|
7
|
+
end
|
8
|
+
|
9
|
+
ruby_version_is "" ... "1.9" do
|
10
|
+
# JRuby doesn't support "_instantiate?" intentionally (JRUBY-2239)
|
11
|
+
not_compliant_on :jruby do
|
12
|
+
it "returns nil until it is instantiated" do
|
13
|
+
SingletonSpecs::NotInstantiated.send(:_instantiate?).should == nil
|
14
|
+
SingletonSpecs::NotInstantiated.instance
|
15
|
+
inst = SingletonSpecs::NotInstantiated.send(:_instantiate?)
|
16
|
+
inst.should eql(SingletonSpecs::NotInstantiated.instance)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/spec/load_spec.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
2
|
+
|
3
|
+
# TODO: change to a.should be_equal(b)
|
4
|
+
# TODO: write spec for cloning classes and calling private methods
|
5
|
+
# TODO: write spec for private_methods not showing up via extended
|
6
|
+
describe "Singleton._load" do
|
7
|
+
ruby_version_is "1.8.7".."1.9" do
|
8
|
+
it "returns the singleton instance for anything passed in" do
|
9
|
+
klass = SingletonSpecs::MyClass
|
10
|
+
klass._load("").should equal(klass.instance)
|
11
|
+
klass._load("42").should equal(klass.instance)
|
12
|
+
klass._load(42).should equal(klass.instance)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "returns the singleton instance for anything passed in to subclass" do
|
16
|
+
subklass = SingletonSpecs::MyClassChild
|
17
|
+
subklass._load("").should equal(subklass.instance)
|
18
|
+
subklass._load("42").should equal(subklass.instance)
|
19
|
+
subklass._load(42).should equal(subklass.instance)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/spec/new_spec.rb
ADDED
metadata
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubysl-singleton
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brian Shirai
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-09-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: mspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubysl-prettyprint
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.0'
|
69
|
+
description: Ruby standard library singleton.
|
70
|
+
email:
|
71
|
+
- brixen@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- .gitignore
|
77
|
+
- .travis.yml
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- lib/rubysl/singleton.rb
|
83
|
+
- lib/rubysl/singleton/singleton.rb
|
84
|
+
- lib/rubysl/singleton/version.rb
|
85
|
+
- lib/singleton.rb
|
86
|
+
- rubysl-singleton.gemspec
|
87
|
+
- spec/allocate_spec.rb
|
88
|
+
- spec/clone_spec.rb
|
89
|
+
- spec/dump_spec.rb
|
90
|
+
- spec/dup_spec.rb
|
91
|
+
- spec/fixtures/classes.rb
|
92
|
+
- spec/instance_spec.rb
|
93
|
+
- spec/instantiate_spec.rb
|
94
|
+
- spec/load_spec.rb
|
95
|
+
- spec/new_spec.rb
|
96
|
+
homepage: https://github.com/rubysl/rubysl-singleton
|
97
|
+
licenses:
|
98
|
+
- BSD
|
99
|
+
metadata: {}
|
100
|
+
post_install_message:
|
101
|
+
rdoc_options: []
|
102
|
+
require_paths:
|
103
|
+
- lib
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - '>='
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - '>='
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
requirements: []
|
115
|
+
rubyforge_project:
|
116
|
+
rubygems_version: 2.0.3
|
117
|
+
signing_key:
|
118
|
+
specification_version: 4
|
119
|
+
summary: Ruby standard library singleton.
|
120
|
+
test_files:
|
121
|
+
- spec/allocate_spec.rb
|
122
|
+
- spec/clone_spec.rb
|
123
|
+
- spec/dump_spec.rb
|
124
|
+
- spec/dup_spec.rb
|
125
|
+
- spec/fixtures/classes.rb
|
126
|
+
- spec/instance_spec.rb
|
127
|
+
- spec/instantiate_spec.rb
|
128
|
+
- spec/load_spec.rb
|
129
|
+
- spec/new_spec.rb
|
130
|
+
has_rdoc:
|