lib/og/store.rb in og-0.31.0 vs lib/og/store.rb in og-0.40.0

- old
+ new

@@ -1,163 +1,166 @@ module Og -# A Store is responsible for the peristance of the ObjectGraph. +# A Store is a backend of Og used to persist objects. An +# adapter specializes the Store. For example the SQL Store +# has the MySQL, PostgreSQL, Sqlite3 etc adapters as +# specializations. class Store - # Options. + attr_accessor :ogmanager - attr_accessor :options - - # Transaction nesting. - - attr_accessor :transaction_nesting - - # :section: Store methods. - - # Return the store for the given name. - - def self.for_name(name) - Logger.info "Og uses the #{name.to_s.capitalize} store." - # gmosx: to keep RDoc happy. - require('og/store/' + name.to_s) - return Og.const_get("#{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. + # + # === Default options + # + # * :evolve_schema => :warn - def initialize(options) - @options = options + def initialize options + @options = { + :evolve_schema => :warn + }.merge(options) @transaction_nesting = 0 end # Close the session to the store. def close + raise 'Not implemented' end - + # Enchants a class. def enchant(klass, manager) - # gmosx, FIXME: - # ARGH, have to update this! - # - # klass.class.send(:define_method, :index) do |arg| - # meta :index, arg - # end - - pk = klass.primary_key.symbol - + pk = klass.primary_key klass.module_eval %{ + + # A managed object is considered saved if it has + # a valid primary key. + def saved? - return #{klass.primary_key.symbol} + return #{pk} end + # The inverse of saved. + def unsaved? - return !#{klass.primary_key.symbol} + return !#{pk} end # Evaluate an alias for the primary key. alias_method :pk, :#{pk} alias_method :pk=, :#{pk}= - - def self.pk_symbol - :#{klass.primary_key.symbol} - end } - end - + # :section: Lifecycle methods. # Loads an object from the store using the primary key. def load(pk, klass) + raise 'Not implemented' end + alias_method :exist?, :load # Reloads an object from the store. def reload(obj) + raise 'Not implemented' end # Save an object to store. Insert if this is a new object or - # update if this is already inserted in the database. + # update if this is already inserted in the database. Checks + # if the object is valid before saving. Returns false if the + # object is invalid and populates obj.errors. def save(obj, options = nil) return false unless obj.valid? if obj.saved? - obj.og_update(self, options) + update_count = obj.og_update(self, options) else - obj.og_insert(self) + update_count = 1 if obj.og_insert(self) end + + # Save building collections if any. + obj.save_building_collections + + return update_count end alias_method :<<, :save alias_method :validate_and_save, :save + # Force the persistence of an Object. Ignore any validation + # and/or other errors. + def force_save!(obj, options) if obj.saved? - obj.og_update(self, options) + obj.og_update self, options else - obj.og_insert(self) + obj.og_insert self end end # Insert an object in the store. def insert(obj) - obj.og_insert(self) + obj.og_insert self end # Update an object in the store. - def update(obj, options = nil) - obj.og_update(self, options) + def update obj, options = nil + obj.og_update self, options end - # Update selected properties of an object or class of + # Update selected attributes of an object or class of # objects. - - def update_properties(obj_or_class, props, options = nil) + + def update_attributes target, *attributes + update(target, :only => attributes) end - alias_method :pupdate, :update_properties - alias_method :update_property, :update_properties + alias_method :aupdate, :update_attributes + alias_method :update_attribute, :update_attributes # 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 + unless obj_or_pk.is_a? EntityMixin + # create an 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) + # methods. This even allows to call og_delete aspects + # that use instance variable (for example, sophisticated + # cache sweepers). + # + # gmosx: the following is not enough! + # obj = klass.allocate + # obj.pk = obj_or_pk + obj = klass[obj_or_pk] + obj.og_delete(self, cascade) else - obj_or_pk.og_delete(self, nil, cascade) + obj_or_pk.og_delete(self, cascade) end end + # Delete all instances of the given class. + + def delete_all(klass) + raise 'Not implemented' + end + # Perform a query. def find(klass, options) + raise 'Not implemented' end # Count the results returned by the query. def count(options) + raise 'Not implemented' end # :section: Transaction methods. # Start a new transaction. @@ -189,32 +192,23 @@ def transaction(&block) begin start yield(self) commit - rescue => ex + rescue Object => ex rollback raise ex end end private - def eval_og_insert(klass) + #-- + # A helper for inserting advices in the precompiled methods. + #++ + + def insert_advices where, target, klass, advices # :nodoc: all + Aspects.gen_advice_code(target, klass.send(advices), where) if klass.respond_to?(advices) end - - def eval_og_update(klass) - end - - def eval_og_read(klass) - end - - def eval_og_delete(klass) - end - - def eval_og_create_schema(klass) - end end end - -# * George Moschovitis <gm@navel.gr>