Class: Hyperactive::Record::Bass

Inherits:
Object
  • Object
show all
Defined in:
lib/hyperactive/record.rb

Overview

A convenient base class to inherit when you want the basic utility methods provided by for example ActiveRecord::Base *hint hint*.

NB: After an instance is created, it will actually return a copy within your local machine which is not what is usually the case. Every other time you fetch it using a select or other method you will instead receive a proxy object to the database. This means that nothing you do to it at that point will be persistent or even necessarily have a defined result. Therefore: do not use MyRecordSubclass.new to MyRecordSubclass#initialize objects, instead use MyRecordSubclass.get_instance, since it will return a fresh proxy object instead of the devious original:

my_instance = MyRecordSubclass.get_instance(*the_same_arguments_as_to_initialize)

Direct Known Subclasses

List::Element, List::Head, Tree::Root

Constant Summary collapse

HOST =

The host we are running on.

"#{Socket::gethostbyname(Socket::gethostname)[0]}" rescue "localhost"
@@create_hooks_by_class =
{}
@@destroy_hooks_by_class =
{}
@@save_hooks_by_class =
{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#record_idObject (readonly)

Our semi-unique id.



339
340
341
# File 'lib/hyperactive/record.rb', line 339

def record_id
  @record_id
end

Class Method Details

.create_hooksObject

Return our create_hooks, which can then be treated as any old Array.

These must be callable objects with an arity of 1 that will be sent the instance about to be created (initial insertion into the database system) that take a block argument.

The block argument will be a Proc that actually injects the instance into the database system.

Use this to preprocess, validate and/or postprocess your instances upon creation.



200
201
202
# File 'lib/hyperactive/record.rb', line 200

def self.create_hooks
  self.get_hook_array_by_class(@@create_hooks_by_class)
end

.destroy_hooksObject

Return our destroy_hooks, which can then be treated as any old Array.

These must be callable objects with an arity of 1 that will be sent the instance about to be destroyed (removal from the database system) that take a block argument.

The block argument will be a Proc that actually removes the instance from the database system.

Use this to preprocess, validate and/or postprocess your instances upon destruction.



217
218
219
# File 'lib/hyperactive/record.rb', line 217

def self.destroy_hooks
  self.get_hook_array_by_class(@@destroy_hooks_by_class)
end

.find(record_id) ⇒ Object

Return the record with record_id.



305
306
307
# File 'lib/hyperactive/record.rb', line 305

def self.find(record_id)
  CAPTAIN[record_id]
end

.get_instance(*arguments) ⇒ Object

Use this method to get new instances of this class, since it will actually make sure it both resides in the database and return a proxy to the remote object.



321
322
323
324
325
326
327
328
329
330
331
332
333
334
# File 'lib/hyperactive/record.rb', line 321

def self.get_instance(*arguments)
  instance = self.new(*arguments)
  instance.instance_eval do
    @record_id = Digest::SHA1.hexdigest("#{HOST}:#{Time.new.to_f}:#{self.object_id}:#{rand(1 << 32)}")
  end
  
  Hyperactive::Hooker.call_with_hooks(instance, *self.create_hooks) do
    CAPTAIN[instance.record_id] = instance
  end
  
  proxy = CAPTAIN[instance.record_id]
  
  return proxy
end

.index_by(*attributes) ⇒ Object

Create an index for this class.

Will create a method find_by_#attributesattributes.join(“<em>and</em>”) for this class that will return what you expect.



245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/hyperactive/record.rb', line 245

def self.index_by(*attributes)
  attribute_key_part = IndexBuilder.get_attribute_key_part(attributes)
  self.class_eval <<END
def self.find_by_#{attributes.join("_and_")}(*args)
key = "#{attribute_key_part}::" + IndexBuilder.get_value_key_part(args)
CAPTAIN[key]
end
END
  index_builder = IndexBuilder.new(attributes)
  self.save_hooks << index_builder
  self.destroy_hooks << index_builder
end

.reject(name, &block) ⇒ Object

Will define a method called name that will include all existing instances of this class that when sent to matcher.call does not return true. Will only return instances saved after this rejector is defined.



286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/hyperactive/record.rb', line 286

def self.reject(name, &block)
  key = self.collection_key(name)
  CAPTAIN[key] ||= Hyperactive::Tree::Root.get_instance
  self.class_eval <<END
def self.#{name}
    CAPTAIN["#{key}"]
end
END
  self.save_hooks << MatchSaver.new(key, Proc.new do |arg|
                                      yield(arg)
                                    end, :reject)
  self.destroy_hooks << MatchSaver.new(key, Proc.new do |arg|
                                         yield(arg)
                                       end, :delete_unless_match)
end

.save_hooksObject

Return our save_hooks, which can then be treated as any old Array.

These must be callable objects with an arity of 1 that will be sent [the old version, the new version] of the instance about to be saved (storage into the database system) along with a block argument.

The block argument will be a Proc that actually saves the instance into the database system.

Use this to preprocess, validate and/or postprocess your instances upon saving.



235
236
237
# File 'lib/hyperactive/record.rb', line 235

def self.save_hooks
  self.get_hook_array_by_class(@@save_hooks_by_class)
end

.select(name, &block) ⇒ Object

Will define a method called name that will include all existing instances of this class that when sent to matcher.call return true. Will only return instances saved after this selector is defined.



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/hyperactive/record.rb', line 264

def self.select(name, &block)
  key = self.collection_key(name)
  CAPTAIN[key] ||= Hyperactive::Tree::Root.get_instance
  self.class_eval <<END
def self.#{name}
    CAPTAIN["#{key}"]
end
END
  self.save_hooks << MatchSaver.new(key, Proc.new do |arg|
                                      yield(arg)
                                    end, :select)
  self.destroy_hooks << MatchSaver.new(key, Proc.new do |arg|
                                         yield(arg)
                                       end, :delete_if_match)
end

.setup(options = {}) ⇒ Object

Call this if you want to change the default database connector to something else.



183
184
185
# File 'lib/hyperactive/record.rb', line 183

def self.setup(options = {})
  CAPTAIN.setup(options[:pirate_options])
end

.transaction(&block) ⇒ Object

Will execute block within a transaction.



312
313
314
# File 'lib/hyperactive/record.rb', line 312

def self.transaction(&block)
  CAPTAIN.transaction(&block)
end

Instance Method Details

#destroyObject

Remove this instance from the database calling all the right hooks.

Freezes this instance after having deleted it.

Returns false without destroying anything if any of the @@pre_destroy_hooks returns false.

Returns true otherwise.



363
364
365
366
367
368
# File 'lib/hyperactive/record.rb', line 363

def destroy
  Hyperactive::Hooker.call_with_hooks(self, *self.class.destroy_hooks) do
    CAPTAIN.delete(@record_id)
    self.freeze
  end
end

#save_hook(old_value, &block) ⇒ Object

This will allow us to wrap any write of us to persistent storage in the @@save_hooks as long as the Archipelago::Hashish provider supports it. See Archipelago::Hashish::BerkeleyHashish for an example of Hashish providers that do this.



347
348
349
350
351
# File 'lib/hyperactive/record.rb', line 347

def save_hook(old_value, &block)
  Hyperactive::Hooker.call_with_hooks([old_value, self], *self.class.save_hooks) do
    yield
  end
end