hyperactive 0.2.3 → 0.2.4

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.
@@ -25,133 +25,17 @@ require 'archipelago'
25
25
  #
26
26
  module Hyperactive
27
27
 
28
+ #
29
+ # The default database connector.
30
+ #
31
+ CAPTAIN = Archipelago::Pirate::Captain.new
32
+
28
33
  #
29
34
  # The package containing the base class Bass that simplifies
30
35
  # using archipelago for generic database stuff.
31
36
  #
32
37
  module Record
33
38
 
34
- #
35
- # The default database connector.
36
- #
37
- CAPTAIN = Archipelago::Pirate::Captain.new
38
-
39
- #
40
- # A tiny <b>call</b>able class that saves stuff in
41
- # indexes depending on certain attributes.
42
- #
43
- class IndexBuilder
44
- #
45
- # Get the first part of the key, that depends on the +attributes+.
46
- #
47
- def self.get_attribute_key_part(attributes)
48
- "Hyperactive::IndexBuilder::#{attributes.join(",")}"
49
- end
50
- #
51
- # Get the last part of the key, that depends on the +values+.
52
- #
53
- def self.get_value_key_part(values)
54
- "#{values.join(",")}"
55
- end
56
- #
57
- # Initialize an IndexBuilder giving it an array of +attributes+
58
- # that will be indexed.
59
- #
60
- def initialize(attributes)
61
- @attributes = attributes
62
- end
63
- #
64
- # Get the key for the given +record+.
65
- #
66
- def get_key_for(record)
67
- values = @attributes.collect do |att|
68
- if record.respond_to?(att)
69
- record.send(att)
70
- else
71
- nil
72
- end
73
- end
74
- key = "#{self.class.get_attribute_key_part(@attributes)}::#{self.class.get_value_key_part(values)}"
75
- end
76
- #
77
- # Call this IndexBuilder and pass it a +block+.
78
- #
79
- # If the +argument+ is an Array then we know we are a save hook,
80
- # otherwise we are a destroy hook.
81
- #
82
- def call(argument, &block)
83
- yield
84
-
85
- #
86
- # If the argument is an Array (of old value, new value)
87
- # then we are a save hook, otherwise a destroy hook.
88
- #
89
- if Array === argument
90
- record = argument.last
91
- old_record = argument.first
92
- old_key = get_key_for(old_record)
93
- new_key = get_key_for(record)
94
- if old_key != new_key
95
- (CAPTAIN[old_key] ||= Hyperactive::Hash::Head.get_instance_with_transaction(record.transaction)).delete(record.record_id)
96
- (CAPTAIN[new_key] ||= Hyperactive::Hash::Head.get_instance_with_transaction(record.transaction))[record.record_id] = record
97
- end
98
- else
99
- record = argument
100
- (CAPTAIN[get_key_for(record)] ||= Hyperactive::Hash::Head.get_instance_with_transaction(record.transaction)).delete(record.record_id)
101
- end
102
- end
103
- end
104
-
105
- #
106
- # A tiny <b>call</b>able class that saves stuff inside containers
107
- # if they match certain criteria.
108
- #
109
- class MatchSaver
110
- #
111
- # Initialize this MatchSaver with a +key+, a <b>call</b>able +matcher+
112
- # and a +mode+ (:select, :reject, :delete_if_match or :delete_unless_match).
113
- #
114
- def initialize(key, matcher, mode)
115
- @key = key
116
- @matcher = matcher
117
- @mode = mode
118
- end
119
- #
120
- # Depending on <i>@mode</i> and return value of <i>@matcher</i>.call
121
- # may save record in the Hash-like container named <i>@key</i> in
122
- # the main database after having yielded to +block+.
123
- #
124
- def call(argument, &block)
125
- yield
126
-
127
- record = argument
128
- record = argument.last if Array === argument
129
-
130
- case @mode
131
- when :select
132
- if @matcher.call(record)
133
- CAPTAIN[@key, record.transaction][record.record_id] = record
134
- else
135
- CAPTAIN[@key, record.transaction].delete(record.record_id)
136
- end
137
- when :reject
138
- if @matcher.call(record)
139
- CAPTAIN[@key, record.transaction].delete(record.record_id)
140
- else
141
- CAPTAIN[@key, record.transaction][record.record_id] = record
142
- end
143
- when :delete_if_match
144
- if @matcher.call(record)
145
- CAPTAIN[@key, record.transaction].delete(record.record_id)
146
- end
147
- when :delete_unless_match
148
- unless @matcher.call(record)
149
- CAPTAIN[@key, record.transaction].delete(record.record_id)
150
- end
151
- end
152
- end
153
- end
154
-
155
39
  #
156
40
  # A convenient base class to inherit when you want the basic utility methods
157
41
  # provided by for example ActiveRecord::Base *hint hint*.
@@ -164,201 +48,17 @@ module Hyperactive
164
48
  # to get a proxy to the object stored into the database.
165
49
  #
166
50
  class Bass
167
-
168
- @@create_hooks_by_class = {}
169
- @@destroy_hooks_by_class = {}
170
- @@save_hooks_by_class = {}
171
- @@load_hooks_by_class = {}
172
51
 
52
+ include Hyperactive::Index::Indexable
53
+ include Hyperactive::Transactions::Accessors
54
+ include Hyperactive::Transactions::Participant
55
+ include Hyperactive::Hooker::Pimp
56
+
173
57
  #
174
58
  # The host we are running on.
175
59
  #
176
60
  HOST = "#{Socket::gethostbyname(Socket::gethostname)[0]}" rescue "localhost"
177
61
 
178
- #
179
- # Call this if you want to change the default database connector
180
- # to something else.
181
- #
182
- def self.setup(options = {})
183
- CAPTAIN.setup(options[:pirate_options])
184
- end
185
-
186
- #
187
- # Works like normal attr_reader but with transactional awareness.
188
- #
189
- def self.attr_reader(*attributes)
190
- attributes.each do |attribute|
191
- define_method(attribute) do
192
- value = instance_variable_get("@#{attribute}")
193
- if Archipelago::Treasure::Dubloon === value
194
- if @transaction ||= nil
195
- return value.join(@transaction)
196
- else
197
- return value
198
- end
199
- else
200
- return value
201
- end
202
- end
203
- end
204
- end
205
-
206
- #
207
- # Works like normal attr_writer but with transactional awareness.
208
- #
209
- def self.attr_writer(*attributes)
210
- attributes.each do |attribute|
211
- define_method("#{attribute}=") do |new_value|
212
- if Archipelago::Treasure::Dubloon === new_value
213
- new_value.assert_transaction(@transaction) if @transaction ||= nil
214
- instance_variable_set("@#{attribute}", new_value)
215
- else
216
- instance_variable_set("@#{attribute}", new_value)
217
- end
218
- end
219
- end
220
- end
221
-
222
- #
223
- # Works like normal attr_accessor but with transactional awareness.
224
- #
225
- def self.attr_accessor(*attributes)
226
- attr_reader(*attributes)
227
- attr_writer(*attributes)
228
- end
229
-
230
- #
231
- # Return our create_hooks, which can then be treated as any old Array.
232
- #
233
- # These must be <b>call</b>able objects with an arity of 1
234
- # that will be sent the instance about to be created (initial
235
- # insertion into the database system) that take a block argument.
236
- #
237
- # The block argument will be a Proc that actually injects the
238
- # instance into the database system.
239
- #
240
- # Use this to preprocess, validate and/or postprocess your
241
- # instances upon creation.
242
- #
243
- def self.create_hooks
244
- self.get_hook_array_by_class(@@create_hooks_by_class)
245
- end
246
-
247
- #
248
- # Return our destroy_hooks, which can then be treated as any old Array.
249
- #
250
- # These must be <b>call</b>able objects with an arity of 1
251
- # that will be sent the instance about to be destroyed (removal
252
- # from the database system) that take a block argument.
253
- #
254
- # The block argument will be a Proc that actually removes the
255
- # instance from the database system.
256
- #
257
- # Use this to preprocess, validate and/or postprocess your
258
- # instances upon destruction.
259
- #
260
- def self.destroy_hooks
261
- self.get_hook_array_by_class(@@destroy_hooks_by_class)
262
- end
263
-
264
- #
265
- # Return our load_hooks, which can then be treated as any old Array.
266
- #
267
- # These must be <b>call</b>able objects with an arity of 1
268
- # that will be sent the instance about to be loaded (insertion
269
- # into the live hash of the database in question) that take a block argument.
270
- #
271
- # The block argument will be a Proc that actually puts the
272
- # instance into the live hash.
273
- #
274
- # Use this to preprocess, validate and/or postprocess your
275
- # instances upon loading.
276
- #
277
- def self.load_hooks
278
- self.get_hook_array_by_class(@@load_hooks_by_class)
279
- end
280
-
281
- #
282
- # Return our save_hooks, which can then be treated as any old Array.
283
- #
284
- # These must be <b>call</b>able objects with an arity of 1
285
- # that will be sent [the old version, the new version] of the
286
- # instance about to be saved (storage into the database system)
287
- # along with a block argument.
288
- #
289
- # The block argument will be a Proc that actually saves the
290
- # instance into the database system.
291
- #
292
- # Use this to preprocess, validate and/or postprocess your
293
- # instances upon saving.
294
- #
295
- def self.save_hooks
296
- self.get_hook_array_by_class(@@save_hooks_by_class)
297
- end
298
-
299
- #
300
- # Create an index for this class.
301
- #
302
- # Will create a method find_by_#{attributes.join("_and_")} for this
303
- # class that will return what you expect.
304
- #
305
- def self.index_by(*attributes)
306
- attribute_key_part = IndexBuilder.get_attribute_key_part(attributes)
307
- self.class_eval <<END
308
- def self.find_by_#{attributes.join("_and_")}(*args)
309
- key = "#{attribute_key_part}::" + IndexBuilder.get_value_key_part(args)
310
- CAPTAIN[key]
311
- end
312
- END
313
- index_builder = IndexBuilder.new(attributes)
314
- self.save_hooks << index_builder
315
- self.destroy_hooks << index_builder
316
- end
317
-
318
- #
319
- # Will define a method called +name+ that will include all
320
- # existing instances of this class that when sent to +matcher+.call
321
- # return true. Will only return instances saved after this selector
322
- # is defined.
323
- #
324
- def self.select(name, &block)
325
- key = self.collection_key(name)
326
- CAPTAIN[key] ||= Hyperactive::Hash::Head.get_instance
327
- self.class_eval <<END
328
- def self.#{name}
329
- CAPTAIN["#{key}"]
330
- end
331
- END
332
- self.save_hooks << MatchSaver.new(key, Proc.new do |arg|
333
- yield(arg)
334
- end, :select)
335
- self.destroy_hooks << MatchSaver.new(key, Proc.new do |arg|
336
- yield(arg)
337
- end, :delete_if_match)
338
- end
339
-
340
- #
341
- # Will define a method called +name+ that will include all
342
- # existing instances of this class that when sent to +matcher+.call
343
- # does not return true. Will only return instances saved after this
344
- # rejector is defined.
345
- #
346
- def self.reject(name, &block)
347
- key = self.collection_key(name)
348
- CAPTAIN[key] ||= Hyperactive::Hash::Head.get_instance
349
- self.class_eval <<END
350
- def self.#{name}
351
- CAPTAIN["#{key}"]
352
- end
353
- END
354
- self.save_hooks << MatchSaver.new(key, Proc.new do |arg|
355
- yield(arg)
356
- end, :reject)
357
- self.destroy_hooks << MatchSaver.new(key, Proc.new do |arg|
358
- yield(arg)
359
- end, :delete_unless_match)
360
- end
361
-
362
62
  #
363
63
  # Return the record with +record_id+, optionally within a +transaction+.
364
64
  #
@@ -374,22 +74,10 @@ END
374
74
  return instance.create
375
75
  end
376
76
 
377
- #
378
- # Utility method to get a proxy to a within a transaction newly saved instance of this class in one call.
379
- #
380
- def self.get_instance_with_transaction(transaction, *args)
381
- instance = self.new(*args)
382
- return_value = nil
383
- instance.with_transaction(transaction) do
384
- return_value = instance.create
385
- end
386
- return return_value
387
- end
388
-
389
77
  #
390
78
  # Our semi-unique id.
391
79
  #
392
- attr_reader :record_id, :transaction
80
+ attr_reader :record_id
393
81
 
394
82
  #
395
83
  # Utility compare method. Override as you please.
@@ -401,6 +89,11 @@ END
401
89
  0
402
90
  end
403
91
  end
92
+
93
+ def initialize
94
+ @record_id = nil
95
+ @transaction = nil
96
+ end
404
97
 
405
98
  #
406
99
  # Save this Record instance into the distributed database and return a proxy to the saved object.
@@ -410,8 +103,8 @@ END
410
103
  def create
411
104
  @record_id ||= Digest::SHA1.hexdigest("#{HOST}:#{Time.new.to_f}:#{self.object_id}:#{rand(1 << 32)}").to_s
412
105
  @transaction ||= nil
413
-
414
- Hyperactive::Hooker.call_with_hooks(self, *self.class.create_hooks) do
106
+
107
+ self.class.with_hooks(:instance => self, :hooks => self.class.create_hooks) do
415
108
  CAPTAIN[self.record_id, @transaction] = self
416
109
  end
417
110
 
@@ -421,97 +114,17 @@ END
421
114
  end
422
115
 
423
116
  #
424
- # Will execute +block+ within a transaction.
425
- #
426
- # What it does is just set the @transaction instance variable
427
- # before calling the block, and unsetting it after.
428
- #
429
- # This means that any classes that want to be transaction sensitive
430
- # need to take heed regarding the @transaction instance variable.
431
- #
432
- # For example, when creating new Record instances you may want to use
433
- # get_instance_with_transaction(@transaction, *args) to ensure that the
434
- # new instance exists within the same transaction as yourself.
435
- #
436
- # See Hyperactive::List::Head and Hyperactive::Hash::Head for examples of this behaviour.
437
- #
438
- def with_transaction(transaction, &block)
439
- @transaction = transaction
440
- begin
441
- yield
442
- ensure
443
- @transaction = nil
444
- end
445
- end
446
-
447
- #
448
- # This will allow us to wrap any write of us to persistent storage
449
- # in the @@save_hooks as long as the Archipelago::Hashish provider
450
- # supports it. See Archipelago::Hashish::BerkeleyHashish for an example
451
- # of Hashish providers that do this.
452
- #
453
- def save_hook(old_value, &block)
454
- Hyperactive::Hooker.call_with_hooks([old_value, self], *self.class.save_hooks) do
455
- yield
456
- end
457
- end
458
-
459
- #
460
- # This will allow us to wrap any load of us from persistent storage
461
- # in the @@load_hooks as long as the Archipelago::Hashish provider
462
- # supports it. See Archipelago::Hashish::BerkeleyHashish for an example
463
- # of Hashish providers that do this.
464
- #
465
- def load_hook(&block)
466
- Hyperactive::Hooker.call_with_hooks(self, *self.class.load_hooks) do
467
- yield
468
- end
469
- end
470
-
471
- #
472
- # Remove this instance from the database calling all the right hooks.
117
+ # Remove this instance from the database wrapped in our destroy_hooks.
473
118
  #
474
119
  # Freezes this instance after having deleted it.
475
120
  #
476
- # Returns false without destroying anything if any of the @@pre_destroy_hooks
477
- # returns false.
478
- #
479
- # Returns true otherwise.
480
- #
481
121
  def destroy!
482
- Hyperactive::Hooker.call_with_hooks(self, *self.class.destroy_hooks) do
122
+ self.class.with_hooks(:instance => self, :hooks => self.class.destroy_hooks) do
483
123
  CAPTAIN.delete(@record_id, @transaction)
484
124
  self.freeze
485
125
  end
486
126
  end
487
127
 
488
- private
489
-
490
- #
491
- # The key used to store the collection with the given +sym+ as name.
492
- #
493
- def self.collection_key(sym)
494
- "Hyperactive::Record::Bass::collection_key::#{sym}"
495
- end
496
-
497
- #
498
- # Get an Array from +hash+ using <i>self</i> as
499
- # key. If <i>self</i> doesnt exist in the +hash+
500
- # it will recurse by calling the same method in the
501
- # superclass until it has been called in Hyperactive::Record::Base.
502
- #
503
- def self.get_hook_array_by_class(hash)
504
- return hash[self] if hash.include?(self)
505
-
506
- if self == Bass
507
- hash[self] = []
508
- return self.get_hook_array_by_class(hash)
509
- else
510
- hash[self] = self.superclass.get_hook_array_by_class(hash).clone
511
- return self.get_hook_array_by_class(hash)
512
- end
513
- end
514
-
515
128
  end
516
129
  end
517
130
  end
@@ -0,0 +1,154 @@
1
+ # Archipelago - a distributed computing toolkit for ruby
2
+ # Copyright (C) 2006 Martin Kihlgren <zond at troja dot ath dot cx>
3
+ #
4
+ # This program is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU General Public License
6
+ # as published by the Free Software Foundation; either version 2
7
+ # of the License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+
18
+ module Hyperactive
19
+
20
+ #
21
+ # A utility package of transaction handling methods.
22
+ #
23
+ module Transactions
24
+
25
+ #
26
+ # Include this to get methods to do with participating in a transaction.
27
+ #
28
+ module Participant
29
+
30
+ #
31
+ # The transaction we are currently in.
32
+ #
33
+ attr_reader :transaction
34
+
35
+ #
36
+ # Will execute +block+ within a transaction.
37
+ #
38
+ # What it does is just set the @transaction instance variable
39
+ # before calling the block, and unsetting it after.
40
+ #
41
+ # This means that any classes that want to be transaction sensitive
42
+ # need to take heed regarding the @transaction instance variable.
43
+ #
44
+ # For example, when creating new Record instances you may want to use
45
+ # get_instance_with_transaction(@transaction, *args) to ensure that the
46
+ # new instance exists within the same transaction as yourself.
47
+ #
48
+ # See Hyperactive::List::Head and Hyperactive::Hash::Head for examples of this behaviour.
49
+ #
50
+ def with_transaction(transaction, &block)
51
+ @transaction = transaction
52
+ begin
53
+ yield
54
+ ensure
55
+ @transaction = nil
56
+ end
57
+ end
58
+
59
+ #
60
+ # Add our ClassMethods to anyone that includes us.
61
+ #
62
+ def self.append_features(base)
63
+ super
64
+ base.extend(ClassMethods)
65
+ end
66
+
67
+ #
68
+ # Class methods for transaction participants.
69
+ #
70
+ module ClassMethods
71
+ #
72
+ # Utility method to get a proxy to a within a transaction newly saved instance of this class in one call.
73
+ #
74
+ def get_instance_with_transaction(transaction, *args)
75
+ instance = self.new(*args)
76
+ return_value = nil
77
+ instance.with_transaction(transaction) do
78
+ return_value = instance.create
79
+ end
80
+ return return_value
81
+ end
82
+
83
+ end
84
+
85
+ end
86
+
87
+ #
88
+ # Include this to get the default attr_reader at al redefined to be transactionally aware.
89
+ #
90
+ module Accessors
91
+
92
+ #
93
+ # The +base+ class including this will get a our ClassMethods as well.
94
+ #
95
+ def self.append_features(base)
96
+ super
97
+ base.extend(ClassMethods)
98
+ end
99
+
100
+ #
101
+ # The class methods that help us set/get instance variables in a transactionally aware way.
102
+ #
103
+ module ClassMethods
104
+ #
105
+ # Works like normal attr_reader but with transactional awareness.
106
+ #
107
+ def attr_reader(*attributes)
108
+ attributes.each do |attribute|
109
+ define_method(attribute) do
110
+ value = instance_variable_get("@#{attribute}")
111
+ if Archipelago::Treasure::Dubloon === value
112
+ if @transaction ||= nil
113
+ return value.join(@transaction)
114
+ else
115
+ return value
116
+ end
117
+ else
118
+ return value
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ #
125
+ # Works like normal attr_writer but with transactional awareness.
126
+ #
127
+ def attr_writer(*attributes)
128
+ attributes.each do |attribute|
129
+ define_method("#{attribute}=") do |new_value|
130
+ if Archipelago::Treasure::Dubloon === new_value
131
+ new_value.assert_transaction(@transaction) if @transaction ||= nil
132
+ instance_variable_set("@#{attribute}", new_value)
133
+ else
134
+ instance_variable_set("@#{attribute}", new_value)
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ #
141
+ # Works like normal attr_accessor but with transactional awareness.
142
+ #
143
+ def attr_accessor(*attributes)
144
+ attr_reader(*attributes)
145
+ attr_writer(*attributes)
146
+ end
147
+
148
+ end
149
+
150
+ end
151
+
152
+ end
153
+
154
+ end
data/lib/hyperactive.rb CHANGED
@@ -18,6 +18,8 @@
18
18
  $: << File.dirname(__FILE__)
19
19
 
20
20
  require 'hyperactive/hooker'
21
+ require 'hyperactive/index'
22
+ require 'hyperactive/transactions'
21
23
  require 'hyperactive/record'
22
24
  require 'hyperactive/hash'
23
25
  require 'hyperactive/list'
@@ -10,13 +10,13 @@ class HashBenchmark < Test::Unit::TestCase
10
10
  @c2.publish!
11
11
  @tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny1.db")))
12
12
  @tm.publish!
13
- Hyperactive::Record::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
13
+ Hyperactive::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
14
14
  :tranny_description => {:class => 'TestManager'})
15
15
  assert_within(20) do
16
- Set.new(Hyperactive::Record::CAPTAIN.chests.keys) == Set.new([@c.service_id, @c2.service_id])
16
+ Set.new(Hyperactive::CAPTAIN.chests.keys) == Set.new([@c.service_id, @c2.service_id])
17
17
  end
18
18
  assert_within(20) do
19
- Hyperactive::Record::CAPTAIN.trannies.keys == [@tm.service_id]
19
+ Hyperactive::CAPTAIN.trannies.keys == [@tm.service_id]
20
20
  end
21
21
  end
22
22
 
@@ -36,8 +36,8 @@ class HashBenchmark < Test::Unit::TestCase
36
36
  end
37
37
 
38
38
  def test_regular_hash_set_get
39
- Hyperactive::Record::CAPTAIN["h"] = {}
40
- h = Hyperactive::Record::CAPTAIN["h"]
39
+ Hyperactive::CAPTAIN["h"] = {}
40
+ h = Hyperactive::CAPTAIN["h"]
41
41
  r = Hyperactive::Record::Bass.get_instance
42
42
  hash_test("Hash", h, r, 100)
43
43
  end
data/tests/hash_test.rb CHANGED
@@ -19,14 +19,14 @@ class HashTest < Test::Unit::TestCase
19
19
  @c2.publish!
20
20
  @tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny1.db")))
21
21
  @tm.publish!
22
- Hyperactive::Record::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
22
+ Hyperactive::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
23
23
  :tranny_description => {:class => 'TestManager'})
24
- Hyperactive::Record::CAPTAIN.update_services!
24
+ Hyperactive::CAPTAIN.update_services!
25
25
  assert_within(10) do
26
- Hyperactive::Record::CAPTAIN.chests.keys.sort == [@c.service_id, @c2.service_id].sort
26
+ Hyperactive::CAPTAIN.chests.keys.sort == [@c.service_id, @c2.service_id].sort
27
27
  end
28
28
  assert_within(10) do
29
- Hyperactive::Record::CAPTAIN.trannies.keys == [@tm.service_id]
29
+ Hyperactive::CAPTAIN.trannies.keys == [@tm.service_id]
30
30
  end
31
31
  end
32
32
 
@@ -69,7 +69,7 @@ class HashTest < Test::Unit::TestCase
69
69
 
70
70
  h2.each do |k,v|
71
71
  assert_equal(v, h[k])
72
- assert_equal(v, Hyperactive::Record::CAPTAIN[h.record_id][k])
72
+ assert_equal(v, Hyperactive::CAPTAIN[h.record_id][k])
73
73
  end
74
74
  end
75
75