A Manager manages Models. Each Manager is attched to a single Store. Multiple Managers can exist in the same Og application.

Methods
Attributes
[RW] cache The managed object cache. This cache is optional. When used it improves object lookups.
[RW] models The collection of Models (managed classes) managed by this manager.
[RW] name The name of this manager. Useful in the multiple managers scenario.
[RW] options The configuration options.
[RW] store The store used for persistence. This is a virtual field when running in thread_safe mode.
Public Class methods
managed?(klass)

Is the given class managed by any manager?

     # File lib/og/manager.rb, line 289
289:     def managed?(klass)
290:       self.managers.any? { |m| m.managed? klass }
291:     end
managed_classes()

Remove the classes managed by all managers.

     # File lib/og/manager.rb, line 295
295:     def managed_classes
296:       managed = self.managers.collect {|m| m.managed_classes}
297:       managed.flatten
298:     end
managers()

Return all managers defined in this application.

     # File lib/og/manager.rb, line 281
281:     def managers
282:       managers = []
283:       ObjectSpace.each_object(self) { |o| managers << o }
284:       return managers
285:     end
new(options)

Initialize the manager.

Options

:store, :adapter = the adapter/store to use as backend.

    # File lib/og/manager.rb, line 46
46:   def initialize(options)
47:     @options = options
48:     @name = options[:name]
49:     @models = []
50: 
51:     @store_class = Adapter.for_name(options[:adapter] || options[:store])
52:     @store_class.allocate.destroy_db(options) if Og.destroy_schema || options[:destroy]
53:     
54:     init_store()
55:   end
Public Instance methods
close_store()

Used when changing thread_safe mode

    # File lib/og/manager.rb, line 79
79:   def close_store
80:     unless @pool
81:       @store.close
82:     else
83:       @pool.each { |s| s.close }
84:       @pool.clear
85:     end
86:     @pool = nil
87:   end
dump(options = {})

Dump Og managed objects to the filesystem.

This method is also aliased as export
    # File lib/og/dump.rb, line 14
14:   def dump(options = {})
15:     classes = options[:classes] || options[:class] || manageable_classes
16:     basedir = options[:basedir] || 'ogdump'
17:     
18:     FileUtils.makedirs(basedir)
19:     
20:     for c in [ classes ].flatten      
21:       Logger.info "Dumping class '#{c}'"
22:       all = c.all.map { |obj| obj.properties_to_hash }
23:       File.open("#{basedir}/#{c}.yml", 'w') { |f| f << all.to_yaml }
24:     end
25:   end
export(options = {})

Alias for #dump

get_store()

Get a store from the pool. The pool is thread safe and blocks if it is empty.

    # File lib/og/manager.rb, line 92
92:   def get_store
93:     if @pool
94:       @pool.pop
95:     else
96:       @store
97:     end
98:   end
import(options = {})

Alias for #load

init_store()

Alias for #initialize_store

initialize_store()

Initialize a store.

This method is also aliased as init_store
    # File lib/og/manager.rb, line 59
59:   def initialize_store
60:     if @pool
61:       close_store
62:     end
63: 
64:     if Og.thread_safe
65:       @pool = Pool.new
66:       (options[:connection_count] || 5).times do
67:         @pool << @store_class.new(@options)
68:         @pool.last.ogmanager = self
69:       end
70:     else
71:       @store = @store_class.new(@options)
72:       @store.ogmanager = self
73:     end
74:   end
load(options = {})

Load Og managed objects from the filesystem. This method can apply optional transformation rules in order to evolve a schema.

This method is also aliased as import
    # File lib/og/dump.rb, line 31
31:   def load(options = {})
32:     classes = options[:classes] || manageable_classes
33:     basedir = options[:basedir] || 'ogdump'
34:     rules = options[:rules] || rules[:evolution] || {}
35: 
36:     classes.each { |c| c.destroy if managed?(c) }
37:     unmanage_classes(classes)
38:     manage_classes
39:     
40:     for f in Dir["#{basedir}/*.yml"]
41:       all = YAML.load(File.read(f))
42:       
43:       unless all.empty?
44:         klass = f.split(/\/|\./)[1]
45:         
46:         Logger.info "Loading class '#{klass}'"
47:         
48:         if krules = rules[klass.to_sym]
49:           if krules[:self]
50:             # Class name changed.
51:             Logger.info "Renaming class '#{klass}' to '#{krules[:self]}'"
52:             klass = krules[:self]
53:           end
54:           
55:           Logger.info "Evolution transformation will be applied!"
56:         end      
57: 
58:         klass = constant(klass)
59:         
60:         for h in all
61:           obj = klass.allocate
62:           obj.assign_with(h)
63:           if krules
64:             krules.each do |old, new|
65:               obj.instance_variable_set "@#{new}", h[old]
66:             end
67:           end
68:           obj.insert
69:         end
70:       end
71:     end
72:   end
manage(klass)

Manage a class. Injects Og related functionality to the class.

     # File lib/og/manager.rb, line 126
126:   def manage(klass)
127:     return if managed?(klass) or (!manageable?(klass))
128: 
129:     # Check if the class has a :text key.
130:     
131:     for a in klass.serializable_attributes
132:       if klass.ann(a, :key)
133:         klass.ann(:self, :text_key => a)
134:         break
135:       end
136:     end
137: 
138:     # DON'T DO THIS!!!
139:     #--
140:     # gmosx: this is used though, dont remove without recoding 
141:     # some stuff.
142:     #++
143:     
144:     klass.module_eval %{
145:       def ==(other)
146:         other.instance_of?(#{klass}) ? @#{klass.primary_key} == other.#{klass.primary_key} : false
147:       end
148:     }
149: 
150:     klass.class.send(:attr_accessor, :ogmanager)
151:     klass.instance_variable_set '@ogmanager', self
152: 
153:     # FIXME: move somewhere else.
154:     
155:     klass.define_force_methods
156: 
157:     Relation.enchant(klass)
158: 
159:     # ensure that the superclass is managed before the
160:     # subclass.
161: 
162:     manage(klass.superclass) if manageable?(klass.superclass)
163: 
164:     # Perform store related enchanting.
165:     
166:     with_store do |s|
167:       s.enchant(klass, self)
168:     end
169: 
170:     # Call special class enchanting code.
171: 
172:     klass.enchant if klass.respond_to?(:enchant)
173:     @models.push(klass).uniq!
174:   end
manage_class(*classes)

Alias for #manage_classes

manage_classes(*classes)

Manage a collection of classes.

This method is also aliased as manage_class
     # File lib/og/manager.rb, line 220
220:   def manage_classes(*classes)
221:     classes.flatten!
222:     classes.compact!
223:     
224:     mc = self.class.managed_classes
225:     
226:     classes = manageable_classes.flatten if classes.empty?
227:     classes = classes.reject { |c| mc.member?(c) || !manageable?(c) }
228:     
229:     sc = @store_class.allocate
230: 
231:     classes.each { |c| sc.force_primary_key(c) } 
232:     classes.each { |c| Relation.resolve_targets(c) }
233:     classes.each { |c| Relation.resolve_polymorphic_markers(c) }
234:     
235:     # The polymorpic resolution step creates more manageable classes.
236:     
237:     classes += classes.map {|c| Relation.resolve_polymorphic_relations(c) }
238:     
239:     classes.flatten!
240:     
241:     classes = classes.reject { |c| !c or self.class.managed?(c) }
242: 
243:     Logger.debug "Og manageable classes: #{classes.inspect}" if $DBG
244: 
245:     classes.each { |c| Relation.resolve_targets(c) }
246:     classes.each { |c| Relation.resolve_names(c) }
247:     classes.each { |c| manage(c) }
248:   end
manageable?(klass)

Is this class manageable by Og?

Unmanageable classes include classes:

  • without serializable attributes
  • explicitly marked as Unmanageable (is Og::Unamanageable)
  • are polymorphic_parents (ie thay are used to spawn polymorphic relations)
     # File lib/og/manager.rb, line 183
183:   def manageable?(klass)
184:     (klass.respond_to?(:serializable_attributes)) and
185:     (!klass.serializable_attributes.empty?) and 
186:     (!Og.unmanageable_classes.include?(klass)) and 
187:     (!klass.polymorphic_parent?)
188:   end
manageable_classes()

Use Ruby’s advanced reflection features to find all manageable classes. Managable are all classes that define Properties.

     # File lib/og/manager.rb, line 206
206:   def manageable_classes
207:     classes = []
208: 
209:     ObjectSpace.each_object(Class) do |c|
210:       if manageable?(c)
211:         classes << c
212:       end
213:     end
214: 
215:     return classes
216:   end
managed?(klass)

Is the class managed by Og?

     # File lib/og/manager.rb, line 192
192:   def managed?(klass)
193:     @models.include?(klass)
194:   end
managed_classes()

Returns an array containing all classes managed by this manager.

     # File lib/og/manager.rb, line 198
198:   def managed_classes
199:     @models
200:   end
post_setup()

Allows functionality that requires a store is finalized to be implemented. A vastly superior method of constructing foreign key constraints is an example of functionality this provides. Currently only used by the PostgreSQL store. Another good use for this would be an alternate table and field creation routine, which could be much faster, something I intend to do to the PostgreSQL store if nobody has reasons for objecting.

     # File lib/og/manager.rb, line 271
271:   def post_setup
272:     with_store do |s|  
273:       s.post_setup if s.respond_to?(:post_setup)
274:     end
275:   end
put_store(store)

Return a store to the pool.

     # File lib/og/manager.rb, line 102
102:   def put_store(store)
103:     if @pool and store
104:       @pool.push(store)
105:     end
106:   end
resolve_polymorphic(klass)

Resolve polymorphic relations.

     # File lib/og/manager.rb, line 119
119:   def resolve_polymorphic(klass)
120:     Relations.resolve_polymorphic(klass)
121:   end
unmanage_class(*classes)

Alias for #unmanage_classes

unmanage_classes(*classes)

Do not manage the given classes.

This method is also aliased as unmanage_class
     # File lib/og/manager.rb, line 253
253:   def unmanage_classes(*classes)
254:     classes = manageable_classes.flatten if classes.empty?
255: 
256:     for c in classes
257:       @models.delete(c)
258:     end
259:   end
with_store() {|store| ...}

Safely work with (multithreaded) stores.

     # File lib/og/manager.rb, line 110
110:   def with_store
111:     store = get_store
112:     return yield(store)
113:   ensure
114:     put_store(store)
115:   end