rhodes 0.3.0 → 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.
- data/Manifest.txt +0 -61
- data/Rakefile +11 -13
- data/lib/rhodes.rb +2 -2
- metadata +33 -77
- data/History.txt +0 -40
- data/README.rdoc +0 -2
- data/bin/rhogen +0 -8
- data/generators/rhogen.rb +0 -131
- data/generators/templates/application/application.rb +0 -4
- data/generators/templates/application/index.erb +0 -11
- data/generators/templates/application/layout.erb +0 -17
- data/generators/templates/model/config.rb +0 -3
- data/generators/templates/model/controller.rb +0 -49
- data/generators/templates/model/edit.erb +0 -21
- data/generators/templates/model/index.erb +0 -10
- data/generators/templates/model/new.erb +0 -16
- data/generators/templates/model/show.erb +0 -6
- data/generators/templates/source/source_adapter.rb +0 -56
- data/lib/ServeME.rb +0 -7
- data/lib/TestServe.rb +0 -9
- data/lib/bsearch.rb +0 -120
- data/lib/builtinME.rb +0 -588
- data/lib/date.rb +0 -1792
- data/lib/date/format.rb +0 -1339
- data/lib/dateME.rb +0 -24
- data/lib/erb.rb +0 -896
- data/lib/find.rb +0 -81
- data/lib/rational.rb +0 -19
- data/lib/rationalME.rb +0 -530
- data/lib/rho.rb +0 -1
- data/lib/rho/render.rb +0 -51
- data/lib/rho/rho.rb +0 -240
- data/lib/rho/rhoapplication.rb +0 -36
- data/lib/rho/rhocontact.rb +0 -110
- data/lib/rho/rhocontroller.rb +0 -35
- data/lib/rho/rhofsconnector.rb +0 -32
- data/lib/rho/rhosupport.rb +0 -139
- data/lib/rho/rhoviewhelpers.rb +0 -121
- data/lib/rhoframework.rb +0 -38
- data/lib/rhofsconnector.rb +0 -1
- data/lib/rhom.rb +0 -1
- data/lib/rhom/rhom.rb +0 -58
- data/lib/rhom/rhom_db_adapter.rb +0 -185
- data/lib/rhom/rhom_db_adapterME.rb +0 -93
- data/lib/rhom/rhom_object.rb +0 -65
- data/lib/rhom/rhom_object_factory.rb +0 -197
- data/lib/rhom/rhom_source.rb +0 -60
- data/lib/singleton.rb +0 -137
- data/lib/time.rb +0 -489
- data/spec/app_generator_spec.rb +0 -33
- data/spec/app_manifest.txt +0 -3
- data/spec/configs/account.rb +0 -3
- data/spec/configs/case.rb +0 -3
- data/spec/configs/employee.rb +0 -3
- data/spec/generator_spec_helper.rb +0 -12
- data/spec/model_generator_spec.rb +0 -36
- data/spec/rho_controller_spec.rb +0 -139
- data/spec/rho_spec.rb +0 -61
- data/spec/rhom_object_factory_spec.rb +0 -132
- data/spec/rhom_spec.rb +0 -45
- data/spec/source_generator_spec.rb +0 -27
- data/spec/spec_helper.rb +0 -48
- data/spec/stubs.rb +0 -31
- data/spec/syncdbtest.sqlite +0 -0
- data/tasks/rspec.rake +0 -34
@@ -1,93 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# rhom_db_adapter.rb
|
3
|
-
# rhodes
|
4
|
-
#
|
5
|
-
# Copyright (C) 2008 Lars Burgess. All rights reserved.
|
6
|
-
#
|
7
|
-
# This program is free software: you can redistribute it and/or modify
|
8
|
-
# it under the terms of the GNU General Public License as published by
|
9
|
-
# the Free Software Foundation, either version 3 of the License, or
|
10
|
-
# (at your option) any later version.
|
11
|
-
#
|
12
|
-
# This program is distributed in the hope that it will be useful,
|
13
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
-
# GNU General Public License for more details.
|
16
|
-
#
|
17
|
-
# You should have received a copy of the GNU General Public License
|
18
|
-
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
-
#
|
20
|
-
require 'rhodes'
|
21
|
-
|
22
|
-
module Rhom
|
23
|
-
class RhomDbAdapter
|
24
|
-
|
25
|
-
@@database = nil
|
26
|
-
|
27
|
-
class << self
|
28
|
-
def open(dbfile=nil)
|
29
|
-
puts "DB name = " + dbfile.inspect
|
30
|
-
unless @@database or dbfile.nil?
|
31
|
-
db = DbAdapter.new(Rhodes::DBVERSION)
|
32
|
-
@@database = db
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
def close
|
38
|
-
if @@database and not @@database.closed?
|
39
|
-
@@database.close
|
40
|
-
@@database = nil
|
41
|
-
else
|
42
|
-
return false
|
43
|
-
end
|
44
|
-
return true
|
45
|
-
end
|
46
|
-
|
47
|
-
# execute a sql statement
|
48
|
-
# optionally, disable the factory processing
|
49
|
-
# which returns the result array directly
|
50
|
-
def execute_sql
|
51
|
-
result = []
|
52
|
-
# Make sure we lock the sync engine's mutex
|
53
|
-
# before we perform a database transaction.
|
54
|
-
# This prevents concurrency issues.
|
55
|
-
begin
|
56
|
-
SyncEngine::lock_sync_mutex
|
57
|
-
result = yield
|
58
|
-
SyncEngine::unlock_sync_mutex
|
59
|
-
rescue Exception => e
|
60
|
-
puts "exception when running query: #{e}"
|
61
|
-
# make sure we unlock even if there's an error!
|
62
|
-
SyncEngine::unlock_sync_mutex
|
63
|
-
end
|
64
|
-
puts "returned #{result.length.to_s} records..."
|
65
|
-
result
|
66
|
-
end
|
67
|
-
|
68
|
-
def select_from_table(table=nil,columns=nil,condition=nil,params=nil)
|
69
|
-
execute_sql { @@database.selectFromTable(table, columns, condition, params) }
|
70
|
-
end
|
71
|
-
|
72
|
-
def insert_into_table(table=nil,values=nil)
|
73
|
-
execute_sql { @@database.insertIntoTable(table, values) }
|
74
|
-
end
|
75
|
-
|
76
|
-
def delete_from_table(table=nil,condition=nil)
|
77
|
-
execute_sql { @@database.deleteFromTable(table, condition) }
|
78
|
-
end
|
79
|
-
|
80
|
-
def delete_all_from_table(table=nil)
|
81
|
-
execute_sql { @@database.deleteAllFromTable(table) }
|
82
|
-
end
|
83
|
-
|
84
|
-
def update_into_table(table=nil,values=nil,condition=nil)
|
85
|
-
execute_sql { @@database.updateIntoTable(table, values, condition) }
|
86
|
-
end
|
87
|
-
end # class methods
|
88
|
-
end # RhomDbAdapter
|
89
|
-
end # Rhom
|
90
|
-
|
91
|
-
at_exit do
|
92
|
-
Rhom::RhomDbAdapter::close
|
93
|
-
end
|
data/lib/rhom/rhom_object.rb
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# rhom_object.rb
|
3
|
-
# rhodes
|
4
|
-
#
|
5
|
-
# Copyright (C) 2008 Lars Burgess. All rights reserved.
|
6
|
-
#
|
7
|
-
# This program is free software: you can redistribute it and/or modify
|
8
|
-
# it under the terms of the GNU General Public License as published by
|
9
|
-
# the Free Software Foundation, either version 3 of the License, or
|
10
|
-
# (at your option) any later version.
|
11
|
-
#
|
12
|
-
# This program is distributed in the hope that it will be useful,
|
13
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
-
# GNU General Public License for more details.
|
16
|
-
#
|
17
|
-
# You should have received a copy of the GNU General Public License
|
18
|
-
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
-
#
|
20
|
-
module Rhom
|
21
|
-
module RhomObject
|
22
|
-
# defines a method at runtime for the
|
23
|
-
# dynamically created class
|
24
|
-
|
25
|
-
|
26
|
-
# we override method_missing here so that instance variables,
|
27
|
-
# when retrieved or set, are added to the object
|
28
|
-
def method_missing(name, *args)
|
29
|
-
unless name == Fixnum
|
30
|
-
varname = name.to_s.gsub(/=/,"")
|
31
|
-
setting = (name.to_s =~ /=/)
|
32
|
-
inst_var = nil
|
33
|
-
|
34
|
-
if setting
|
35
|
-
inst_var = instance_variable_set( "@#{varname}", args[0] )
|
36
|
-
else
|
37
|
-
inst_var = instance_variable_get( "@#{varname}" )
|
38
|
-
end
|
39
|
-
|
40
|
-
inst_var
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def remove_var(name)
|
45
|
-
remove_instance_variable("@#{name}")
|
46
|
-
end
|
47
|
-
|
48
|
-
def strip_braces(str=nil)
|
49
|
-
str ? str.gsub(/\{/,"").gsub(/\}/,"") : nil
|
50
|
-
end
|
51
|
-
|
52
|
-
# use djb hash function to generate temp object id
|
53
|
-
def djb_hash(str, len)
|
54
|
-
hash = 5381
|
55
|
-
for i in (0..len)
|
56
|
-
hash = ((hash << 5) + hash) + str[i].to_i
|
57
|
-
end
|
58
|
-
return hash
|
59
|
-
end
|
60
|
-
|
61
|
-
def method_name_reserved?(method)
|
62
|
-
method =~ /object|source_id|update_type|type/
|
63
|
-
end
|
64
|
-
end # RhomObject
|
65
|
-
end # Rhom
|
@@ -1,197 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# rhom_object_factory.rb
|
3
|
-
# rhodes
|
4
|
-
# Returns an array of RhomObjects
|
5
|
-
#
|
6
|
-
# Copyright (C) 2008 Lars Burgess. All rights reserved.
|
7
|
-
#
|
8
|
-
# This program is free software: you can redistribute it and/or modify
|
9
|
-
# it under the terms of the GNU General Public License as published by
|
10
|
-
# the Free Software Foundation, either version 3 of the License, or
|
11
|
-
# (at your option) any later version.
|
12
|
-
#
|
13
|
-
# This program is distributed in the hope that it will be useful,
|
14
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
-
# GNU General Public License for more details.
|
17
|
-
#
|
18
|
-
# You should have received a copy of the GNU General Public License
|
19
|
-
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
20
|
-
#
|
21
|
-
require 'rhom'
|
22
|
-
require 'rho'
|
23
|
-
|
24
|
-
module Rhom
|
25
|
-
class RhomObjectFactory
|
26
|
-
|
27
|
-
def initialize
|
28
|
-
unless not defined? Rho::RhoConfig::sources
|
29
|
-
init_objects
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# Initialize new object with dynamic attributes
|
34
|
-
def init_objects
|
35
|
-
Rho::RhoConfig::sources.each do |classname,source|
|
36
|
-
unless Object::const_defined?(classname.intern)
|
37
|
-
Object::const_set(classname.intern,
|
38
|
-
Class::new do
|
39
|
-
include ::Rhom::RhomObject
|
40
|
-
extend ::Rhom::RhomObject
|
41
|
-
|
42
|
-
def initialize(obj=nil)
|
43
|
-
if obj
|
44
|
-
# create a temp id for the create type
|
45
|
-
# TODO: This is duplicative of get_new_obj
|
46
|
-
temp_objid = djb_hash(obj.values.to_s, 10).to_s
|
47
|
-
self.send("object=".to_sym(), temp_objid)
|
48
|
-
self.send("source_id=".to_sym(), obj['source_id'].to_s)
|
49
|
-
self.send("update_type=".to_sym(), 'create')
|
50
|
-
obj.each do |key,value|
|
51
|
-
val = self.inst_strip_braces(value)
|
52
|
-
self.send("#{key}=".to_sym(), val)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|
57
|
-
|
58
|
-
class << self
|
59
|
-
|
60
|
-
def get_source_id
|
61
|
-
Rho::RhoConfig::sources[self.name.to_s]['source_id'].to_s
|
62
|
-
end
|
63
|
-
|
64
|
-
# retrieve a single record if object id provided, otherwise return
|
65
|
-
# full list corresponding to factory's source id
|
66
|
-
def find(*args)
|
67
|
-
list = []
|
68
|
-
hash_list = {}
|
69
|
-
conditions = {}
|
70
|
-
|
71
|
-
# first find all query objects
|
72
|
-
if args.first == :all
|
73
|
-
conditions = {"source_id"=>get_source_id}
|
74
|
-
else
|
75
|
-
conditions = {"object"=>strip_braces(args.first.to_s)}
|
76
|
-
end
|
77
|
-
|
78
|
-
# process query, create, and update lists in order
|
79
|
-
["query", "create", "update"].each do |update_type|
|
80
|
-
conditions.merge!({"update_type"=>update_type})
|
81
|
-
objs = ::Rhom::RhomDbAdapter::select_from_table(::Rhom::TABLE_NAME, '*', conditions,
|
82
|
-
{"order by"=>'object'})
|
83
|
-
objs.collect! do |obj|
|
84
|
-
object = obj['object']
|
85
|
-
attrib = obj['attrib']
|
86
|
-
value = obj['value']
|
87
|
-
hash_list[object] = get_new_obj(obj) if not hash_list[object]
|
88
|
-
if not method_name_reserved?(attrib) and hash_list[object].send(attrib.to_sym)
|
89
|
-
hash_list[object].remove_var(attrib)
|
90
|
-
end
|
91
|
-
hash_list[object].send("#{attrib}=".to_sym(), value) if not method_name_reserved?(attrib)
|
92
|
-
nil # remove the element from the array
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
# convert hash to array
|
97
|
-
list = hash_list.values
|
98
|
-
hash_list = nil
|
99
|
-
if list.length == 1 and args.first != :all
|
100
|
-
return list[0]
|
101
|
-
end
|
102
|
-
list
|
103
|
-
end
|
104
|
-
|
105
|
-
def find_by(*args)
|
106
|
-
# TODO: implement
|
107
|
-
end
|
108
|
-
|
109
|
-
private
|
110
|
-
# returns new model instance with a temp object id
|
111
|
-
def get_new_obj(obj, type='query')
|
112
|
-
tmp_obj = self.new
|
113
|
-
tmp_obj.send("object=".to_sym(), "{#{obj['object'].to_s}}")
|
114
|
-
tmp_obj
|
115
|
-
end
|
116
|
-
end #class methods
|
117
|
-
|
118
|
-
# deletes the record from the viewable list as well as
|
119
|
-
# adding a delete record to the list of sync operations
|
120
|
-
def destroy
|
121
|
-
result = nil
|
122
|
-
obj = self.inst_strip_braces(self.object)
|
123
|
-
if obj
|
124
|
-
# first delete the record from viewable list
|
125
|
-
result = ::Rhom::RhomDbAdapter::delete_from_table(::Rhom::TABLE_NAME,
|
126
|
-
{"object"=>obj})
|
127
|
-
# now add delete operation
|
128
|
-
result = ::Rhom::RhomDbAdapter::insert_into_table(::Rhom::TABLE_NAME,
|
129
|
-
{"source_id"=>self.get_inst_source_id,
|
130
|
-
"object"=>obj,
|
131
|
-
"update_type"=>'delete'})
|
132
|
-
end
|
133
|
-
result
|
134
|
-
end
|
135
|
-
|
136
|
-
# saves the current object to the database as a create type
|
137
|
-
def save
|
138
|
-
result = nil
|
139
|
-
# iterate over each instance variable and insert create row to table
|
140
|
-
obj = self.inst_strip_braces(self.object)
|
141
|
-
self.instance_variables.each do |method|
|
142
|
-
method = method.to_s.gsub(/@/,"")
|
143
|
-
# Don't save objects with braces to database
|
144
|
-
val = self.inst_strip_braces(self.send(method.to_sym))
|
145
|
-
# add rows excluding object, source_id and update_type
|
146
|
-
unless self.method_name_reserved?(method) or val.nil?
|
147
|
-
result = ::Rhom::RhomDbAdapter::insert_into_table(::Rhom::TABLE_NAME,
|
148
|
-
{"source_id"=>self.get_inst_source_id,
|
149
|
-
"object"=>obj,
|
150
|
-
"attrib"=>method,
|
151
|
-
"value"=>val,
|
152
|
-
"update_type"=>'create'})
|
153
|
-
end
|
154
|
-
end
|
155
|
-
result
|
156
|
-
end
|
157
|
-
|
158
|
-
# updates the current record in the viewable list and adds
|
159
|
-
# a sync operation to update
|
160
|
-
def update_attributes(attrs)
|
161
|
-
result = nil
|
162
|
-
obj = self.inst_strip_braces(self.object)
|
163
|
-
self.instance_variables.each do |method|
|
164
|
-
method = method.to_s.gsub(/@/,"")
|
165
|
-
val = self.send method.to_sym
|
166
|
-
# Don't save objects with braces to database
|
167
|
-
new_val = self.inst_strip_braces(attrs[method])
|
168
|
-
# if the object's value doesn't match the database record
|
169
|
-
# then we procede with update
|
170
|
-
if new_val and val != new_val
|
171
|
-
unless self.method_name_reserved?(method) or new_val.length == 0
|
172
|
-
# update sync list
|
173
|
-
result = ::Rhom::RhomDbAdapter::insert_into_table(::Rhom::TABLE_NAME,
|
174
|
-
{"source_id"=>self.get_inst_source_id,
|
175
|
-
"object"=>obj,
|
176
|
-
"attrib"=>method,
|
177
|
-
"value"=>new_val,
|
178
|
-
"update_type"=>'update'})
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
result
|
183
|
-
end
|
184
|
-
|
185
|
-
def get_inst_source_id
|
186
|
-
Rho::RhoConfig::sources[self.class.name.to_s]['source_id'].to_s
|
187
|
-
end
|
188
|
-
|
189
|
-
def inst_strip_braces(str=nil)
|
190
|
-
str ? str.gsub(/\{/,"").gsub(/\}/,"") : nil
|
191
|
-
end
|
192
|
-
end)
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end # RhomObjectFactory
|
197
|
-
end # Rhom
|
data/lib/rhom/rhom_source.rb
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
require 'time'
|
2
|
-
require 'rhom/rhom_object'
|
3
|
-
|
4
|
-
module Rhom
|
5
|
-
class RhomSource
|
6
|
-
include RhomObject
|
7
|
-
attr_accessor :source_url
|
8
|
-
attr_reader :source_id, :name, :last_updated, :last_inserted_size,
|
9
|
-
:last_deleted_size, :last_sync_duration,
|
10
|
-
:last_sync_success, :distinct_objects
|
11
|
-
|
12
|
-
def initialize(args,count=0)
|
13
|
-
# setup the name
|
14
|
-
# TODO: should really store this in the database
|
15
|
-
Rho::RhoConfig::sources.each do |key,value|
|
16
|
-
if value['source_id'].to_i == args['source_id'].to_i
|
17
|
-
@name = key
|
18
|
-
end
|
19
|
-
end
|
20
|
-
@source_id = args['source_id'].to_i
|
21
|
-
@source_url = args['source_url']
|
22
|
-
@last_updated = Time.at(args['last_updated'].to_i).to_s
|
23
|
-
@last_inserted_size = args['last_inserted_size'].to_i
|
24
|
-
@last_deleted_size = args['last_deleted_size'].to_i
|
25
|
-
@last_sync_duration = args['last_sync_duration'].to_i
|
26
|
-
@last_sync_success = args['last_sync_success'].to_i == 1 ? true : false
|
27
|
-
@distinct_objects = ::Rhom::RhomDbAdapter::select_from_table(
|
28
|
-
::Rhom::TABLE_NAME,
|
29
|
-
'object',
|
30
|
-
{"source_id"=>@source_id},
|
31
|
-
{"distinct"=>true}).length
|
32
|
-
end
|
33
|
-
|
34
|
-
class << self
|
35
|
-
include RhomObject
|
36
|
-
def find(*args)
|
37
|
-
list = []
|
38
|
-
if args.first == :all
|
39
|
-
results = ::Rhom::RhomDbAdapter::select_from_table('sources', '*')
|
40
|
-
|
41
|
-
results.each do |result|
|
42
|
-
list << RhomSource.new(result)
|
43
|
-
end
|
44
|
-
else
|
45
|
-
result = ::Rhom::RhomDbAdapter::select_from_table('sources', '*',
|
46
|
-
{"source_id" => strip_braces(args.first)}).first
|
47
|
-
list << RhomSource.new(result)
|
48
|
-
end
|
49
|
-
list.size > 1 ? list : list[0]
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def update_attributes(params=nil)
|
54
|
-
if params
|
55
|
-
::Rhom::RhomDbAdapter::update_into_table('sources', {"source_url"=>params['source_url']},
|
56
|
-
{"source_id"=>strip_braces(params['source_id'])})
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
data/lib/singleton.rb
DELETED
@@ -1,137 +0,0 @@
|
|
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
|
-
# a.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
|