Class: Hyperactive::Record::Bass
- Inherits:
-
Object
- Object
- Hyperactive::Record::Bass
- 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: When an instance is created you will actually have a copy within your local machine which is not what you usually want. 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 the instantiated object, instead call my_instance.save to get a proxy to the object stored into the database.
Direct Known Subclasses
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 =
{}
- @@load_hooks_by_class =
{}
Instance Attribute Summary collapse
-
#record_id ⇒ Object
readonly
Our semi-unique id.
-
#transaction ⇒ Object
readonly
Our semi-unique id.
Class Method Summary collapse
-
.attr_accessor(*attributes) ⇒ Object
Works like normal attr_accessor but with transactional awareness.
-
.attr_reader(*attributes) ⇒ Object
Works like normal attr_reader but with transactional awareness.
-
.attr_writer(*attributes) ⇒ Object
Works like normal attr_writer but with transactional awareness.
-
.create_hooks ⇒ Object
Return our create_hooks, which can then be treated as any old Array.
-
.destroy_hooks ⇒ Object
Return our destroy_hooks, which can then be treated as any old Array.
-
.find(record_id, transaction = nil) ⇒ Object
Return the record with
record_id
, optionally within atransaction
. -
.get_instance(*args) ⇒ Object
Utility method to get a proxy to a newly saved instance of this class in one call.
-
.get_instance_with_transaction(transaction, *args) ⇒ Object
Utility method to get a proxy to a within a transaction newly saved instance of this class in one call.
-
.index_by(*attributes) ⇒ Object
Create an index for this class.
-
.load_hooks ⇒ Object
Return our load_hooks, which can then be treated as any old Array.
-
.reject(name, &block) ⇒ Object
Will define a method called
name
that will include all existing instances of this class that when sent tomatcher
.call does not return true. -
.save_hooks ⇒ Object
Return our save_hooks, which can then be treated as any old Array.
-
.select(name, &block) ⇒ Object
Will define a method called
name
that will include all existing instances of this class that when sent tomatcher
.call return true. -
.setup(options = {}) ⇒ Object
Call this if you want to change the default database connector to something else.
Instance Method Summary collapse
-
#<=>(o) ⇒ Object
Utility compare method.
-
#create ⇒ Object
Save this Record instance into the distributed database and return a proxy to the saved object.
-
#destroy! ⇒ Object
Remove this instance from the database calling all the right hooks.
-
#load_hook(&block) ⇒ Object
This will allow us to wrap any load of us from persistent storage in the @@load_hooks as long as the Archipelago::Hashish provider supports it.
-
#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.
-
#with_transaction(transaction, &block) ⇒ Object
Will execute
block
within a transaction.
Instance Attribute Details
#record_id ⇒ Object (readonly)
Our semi-unique id.
392 393 394 |
# File 'lib/hyperactive/record.rb', line 392 def record_id @record_id end |
#transaction ⇒ Object (readonly)
Our semi-unique id.
392 393 394 |
# File 'lib/hyperactive/record.rb', line 392 def transaction @transaction end |
Class Method Details
.attr_accessor(*attributes) ⇒ Object
Works like normal attr_accessor but with transactional awareness.
225 226 227 228 |
# File 'lib/hyperactive/record.rb', line 225 def self.attr_accessor(*attributes) attr_reader(*attributes) attr_writer(*attributes) end |
.attr_reader(*attributes) ⇒ Object
Works like normal attr_reader but with transactional awareness.
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/hyperactive/record.rb', line 189 def self.attr_reader(*attributes) attributes.each do |attribute| define_method(attribute) do value = instance_variable_get("@#{attribute}") if Archipelago::Treasure::Dubloon === value if @transaction ||= nil return value.join(@transaction) else return value end else return value end end end end |
.attr_writer(*attributes) ⇒ Object
Works like normal attr_writer but with transactional awareness.
209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/hyperactive/record.rb', line 209 def self.attr_writer(*attributes) attributes.each do |attribute| define_method("#{attribute}=") do |new_value| if Archipelago::Treasure::Dubloon === new_value new_value.assert_transaction(@transaction) if @transaction ||= nil instance_variable_set("@#{attribute}", new_value) else instance_variable_set("@#{attribute}", new_value) end end end end |
.create_hooks ⇒ Object
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.
243 244 245 |
# File 'lib/hyperactive/record.rb', line 243 def self.create_hooks self.get_hook_array_by_class(@@create_hooks_by_class) end |
.destroy_hooks ⇒ Object
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.
260 261 262 |
# File 'lib/hyperactive/record.rb', line 260 def self.destroy_hooks self.get_hook_array_by_class(@@destroy_hooks_by_class) end |
.find(record_id, transaction = nil) ⇒ Object
Return the record with record_id
, optionally within a transaction
.
365 366 367 |
# File 'lib/hyperactive/record.rb', line 365 def self.find(record_id, transaction = nil) CAPTAIN[record_id, transaction] end |
.get_instance(*args) ⇒ Object
Utility method to get a proxy to a newly saved instance of this class in one call.
372 373 374 375 |
# File 'lib/hyperactive/record.rb', line 372 def self.get_instance(*args) instance = self.new(*args) return instance.create end |
.get_instance_with_transaction(transaction, *args) ⇒ Object
Utility method to get a proxy to a within a transaction newly saved instance of this class in one call.
380 381 382 383 384 385 386 387 |
# File 'lib/hyperactive/record.rb', line 380 def self.get_instance_with_transaction(transaction, *args) instance = self.new(*args) return_value = nil instance.with_transaction(transaction) do return_value = instance.create end return return_value 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.
305 306 307 308 309 310 311 312 313 314 315 316 |
# File 'lib/hyperactive/record.rb', line 305 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 |
.load_hooks ⇒ Object
Return our load_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 loaded (insertion into the live hash of the database in question) that take a block argument.
The block argument will be a Proc that actually puts the instance into the live hash.
Use this to preprocess, validate and/or postprocess your instances upon loading.
277 278 279 |
# File 'lib/hyperactive/record.rb', line 277 def self.load_hooks self.get_hook_array_by_class(@@load_hooks_by_class) 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.
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 |
# File 'lib/hyperactive/record.rb', line 346 def self.reject(name, &block) key = self.collection_key(name) CAPTAIN[key] ||= Hyperactive::Hash::Head.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_hooks ⇒ Object
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.
295 296 297 |
# File 'lib/hyperactive/record.rb', line 295 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.
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
# File 'lib/hyperactive/record.rb', line 324 def self.select(name, &block) key = self.collection_key(name) CAPTAIN[key] ||= Hyperactive::Hash::Head.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.
182 183 184 |
# File 'lib/hyperactive/record.rb', line 182 def self.setup( = {}) CAPTAIN.setup([:pirate_options]) end |
Instance Method Details
#<=>(o) ⇒ Object
Utility compare method. Override as you please.
397 398 399 400 401 402 403 |
# File 'lib/hyperactive/record.rb', line 397 def <=>(o) if Record === o @record_id <=> o.record_id else 0 end end |
#create ⇒ Object
Save this Record instance into the distributed database and return a proxy to the saved object.
This will also wrap the actual insertion within the create_hooks you have defined for this class.
410 411 412 413 414 415 416 417 418 419 420 421 |
# File 'lib/hyperactive/record.rb', line 410 def create @record_id ||= Digest::SHA1.hexdigest("#{HOST}:#{Time.new.to_f}:#{self.object_id}:#{rand(1 << 32)}").to_s @transaction ||= nil Hyperactive::Hooker.call_with_hooks(self, *self.class.create_hooks) do CAPTAIN[self.record_id, @transaction] = self end proxy = CAPTAIN[@record_id, @transaction] return proxy end |
#destroy! ⇒ Object
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.
481 482 483 484 485 486 |
# File 'lib/hyperactive/record.rb', line 481 def destroy! Hyperactive::Hooker.call_with_hooks(self, *self.class.destroy_hooks) do CAPTAIN.delete(@record_id, @transaction) self.freeze end end |
#load_hook(&block) ⇒ Object
This will allow us to wrap any load of us from persistent storage in the @@load_hooks as long as the Archipelago::Hashish provider supports it. See Archipelago::Hashish::BerkeleyHashish for an example of Hashish providers that do this.
465 466 467 468 469 |
# File 'lib/hyperactive/record.rb', line 465 def load_hook(&block) Hyperactive::Hooker.call_with_hooks(self, *self.class.load_hooks) do yield 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.
453 454 455 456 457 |
# File 'lib/hyperactive/record.rb', line 453 def save_hook(old_value, &block) Hyperactive::Hooker.call_with_hooks([old_value, self], *self.class.save_hooks) do yield end end |
#with_transaction(transaction, &block) ⇒ Object
Will execute block
within a transaction.
What it does is just set the @transaction instance variable before calling the block, and unsetting it after.
This means that any classes that want to be transaction sensitive need to take heed regarding the @transaction instance variable.
For example, when creating new Record instances you may want to use get_instance_with_transaction(@transaction, *args) to ensure that the new instance exists within the same transaction as yourself.
See Hyperactive::List::Head and Hyperactive::Hash::Head for examples of this behaviour.
438 439 440 441 442 443 444 445 |
# File 'lib/hyperactive/record.rb', line 438 def with_transaction(transaction, &block) @transaction = transaction begin yield ensure @transaction = nil end end |