module Og # A Store is responsible for the peristance of the ObjectGraph. class Store # Options. attr_accessor :options # Transaction nesting. attr_accessor :transaction_nesting # :section: Store methods. # Return the store for the given name. def self.for_name(name) # gmosx: to keep RDoc happy. eval %{ require 'og/store/#{name}' return #{name.to_s.capitalize}Store } end # Creates a store. def self.create(options) end # Destroys a store. def self.destroy(options) end # :section: Misc methods. # Create a session to the store. def initialize(options) @options = options @transaction_nesting = 0 end # Close the session to the store. def close end # Enchants a class. def enchant(klass, manager) klass.class.send(:define_method, :index) do |arg| meta :index, arg end pk = klass.primary_key.first klass.module_eval %{ def saved? return @#{klass.primary_key.first} end def unsaved? return !@#{klass.primary_key.first} end # Evaluate an alias for the primary key. alias_method :pk, :#{pk} alias_method :pk=, :#{pk}= def self.pk_symbol :#{klass.primary_key.first} end } # Generate finder methods. code = '' for p in klass.properties # gmosx: :uniq does NOT set a unique constrain in the # database. finder = p.meta[:uniq] || p.meta[:unique] ? 'find_one' : 'find' code << %{ def self.find_by_#{p.symbol}(val, operator = '=', options = {}) options.update( :class => #{klass}, :condition => "#{p.symbol}\#{operator}\#{ogmanager.store.quote(val)}" ) ogmanager.store.#{finder}(options) end; } end klass.module_eval(code) end # :section: Lifecycle methods. # Loads an object from the store using the primary key. def load(pk, klass) end # Reloads an object from the store. def reload(obj) end # Save an object to store. Insert if this is a new object or # update if this is already inserted in the database. def save(obj, options = nil) if obj.saved? obj.og_update(self, options) else obj.og_insert(self) end end alias_method :<<, :save # Insert an object in the store. def insert(obj) obj.og_insert(self) end # Update an object in the store. def update(obj, options = nil) obj.og_update(self, options) end # Update selected properties of an object or class of # objects. def update_properties(obj_or_class, props, options = nil) end alias_method :pupdate, :update_properties alias_method :update_property, :update_properties # Permanently delete an object from the store. def delete(obj_or_pk, klass = nil, cascade = true) unless obj_or_pk.is_a?(EntityMixin) # create a dummy instance to keep the og_delete # method as an instance method like the other lifecycle # methods. klass.allocate.og_delete(self, obj_or_pk, cascade) else obj_or_pk.og_delete(self, nil, cascade) end end # Perform a query. def find(klass, options) end # Count the results returned by the query. def count(options) end # :section: Transaction methods. # Start a new transaction. def start raise 'Not implemented' true if @transaction_nesting < 1 @transaction_nesting += 1 end # Commit a transaction. def commit raise 'Not implemented' @transaction_nesting -= 1 true if @transaction_nesting < 1 end # Rollback a transaction. def rollback @transaction_nesting -= 1 true if @transaction_nesting < 1 end # Transaction helper. In the transaction block use # the db pointer to the backend. def transaction(&block) begin start yield(self) commit rescue => ex Logger.error 'Error in transaction' Logger.error ex Logger.error ex.backtrace rollback end end private def eval_og_insert(klass) end def eval_og_update(klass) end def eval_og_read(klass) end def eval_og_delete(klass) end end end