Class: Og::Manager
- Inherits:
-
Object
- Object
- Og::Manager
- Defined in:
- lib/og/dump.rb,
lib/og/manager.rb
Overview
A Manager defines the relations between entities, ie objects managed by Og.
Defined Under Namespace
Classes: EntityInfo
Instance Attribute Summary collapse
-
#cache ⇒ Object
The managed object cache.
-
#entities ⇒ Object
The collection of Entities (managed classes) managed by this manager.
-
#options ⇒ Object
The configuration options.
-
#store ⇒ Object
The store used for persistence.
Class Method Summary collapse
Instance Method Summary collapse
-
#close_store ⇒ Object
used when changing thread_safe mode.
-
#dump(options = {}) ⇒ Object
(also: #export)
Dump Og managed objects to the filesystem.
-
#get_store ⇒ Object
(also: #store, #conn)
Get a store from the pool.
-
#initialize(options) ⇒ Manager
constructor
Initialize the manager.
-
#initialize_store ⇒ Object
(also: #init_store)
Initialize a store.
-
#load(options = {}) ⇒ Object
(also: #import)
Load Og managed objects from the filesystem.
-
#manage(klass) ⇒ Object
Manage a class.
-
#manage_classes(*classes) ⇒ Object
(also: #manage_class)
Manage a collection of classes.
-
#manageable?(klass) ⇒ Boolean
Is this class manageable by Og?.
-
#manageable_classes ⇒ Object
Use Ruby’s advanced reflection features to find all manageable classes.
-
#managed?(klass) ⇒ Boolean
(also: #entity?)
Is the class managed by Og?.
-
#managed_classes ⇒ Object
Returns an array containing all classes managed by this manager.
-
#post_setup ⇒ Object
Allows functionality that requires a store is finalized to be implemented.
-
#put_store ⇒ Object
Return a store to the pool.
-
#resolve_polymorphic(klass) ⇒ Object
Resolve polymorphic relations.
-
#unmanage_classes(*classes) ⇒ Object
(also: #unmanage_class)
Do not manage the given classes.
Constructor Details
#initialize(options) ⇒ Manager
Initialize the manager.
Options
:store, :adapter = the adapter/store to use as backend.
68 69 70 71 72 73 74 75 76 |
# File 'lib/og/manager.rb', line 68 def initialize() @options = @entities = {} @store_class = Adapter.for_name([:adapter] || [:store]) @store_class.allocate.destroy_db() if Og.destroy_schema || [:destroy] init_store() end |
Instance Attribute Details
#cache ⇒ Object
The managed object cache. This cache is optional. When used it improves object lookups.
60 61 62 |
# File 'lib/og/manager.rb', line 60 def cache @cache end |
#entities ⇒ Object
The collection of Entities (managed classes) managed by this manager.
55 56 57 |
# File 'lib/og/manager.rb', line 55 def entities @entities end |
#options ⇒ Object
The configuration options.
45 46 47 |
# File 'lib/og/manager.rb', line 45 def @options end |
#store=(value) ⇒ Object
The store used for persistence. This is a virtual field when running in thread_safe mode.
50 51 52 |
# File 'lib/og/manager.rb', line 50 def store=(value) @store = value end |
Class Method Details
.managed?(klass) ⇒ Boolean
20 21 22 |
# File 'lib/og/manager.rb', line 20 def self.managed?(klass) self.managers.any? { |m| m.managed? klass } end |
.managed_classes ⇒ Object
24 25 26 27 |
# File 'lib/og/manager.rb', line 24 def self.managed_classes managed = self.managers.collect {|m| m.managed_classes} managed.flatten end |
.managers ⇒ Object
14 15 16 17 18 |
# File 'lib/og/manager.rb', line 14 def self.managers managers = [] ObjectSpace.each_object(self) { |o| managers << o } return managers end |
Instance Method Details
#close_store ⇒ Object
used when changing thread_safe mode
100 101 102 103 104 105 106 107 108 |
# File 'lib/og/manager.rb', line 100 def close_store unless @pool @store.close else @pool.each { |s| s.close } @pool.clear end @pool = nil end |
#dump(options = {}) ⇒ Object Also known as: export
Dump Og managed objects to the filesystem.
14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/og/dump.rb', line 14 def dump( = {}) classes = [:classes] || [:class] || manageable_classes basedir = [:basedir] || 'ogdump' FileUtils.makedirs(basedir) for c in [ classes ].flatten Logger.info "Dumping class '#{c}'" all = c.all.map { |obj| obj.properties_to_hash } File.open("#{basedir}/#{c}.yml", 'w') { |f| f << all.to_yaml } end end |
#get_store ⇒ Object Also known as: store, conn
Get a store from the pool.
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/og/manager.rb', line 112 def get_store if @pool thread = Thread.current unless st = thread[:og_store] and st.is_a?(@store_class) if 0 == @pool.size initialize_store end st = @pool.pop thread[:og_store] = st end if st.ogmanager != self # This normally shound't happen, there is a leftover store. # Just return it to the original store and go on. st.ogmanager.put_store if 0 == @pool.size initialize_store end st = @pool.pop thread[:og_store] = st end return st else return @store end end |
#initialize_store ⇒ Object Also known as: init_store
Initialize a store.
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/og/manager.rb', line 80 def initialize_store if @pool close_store end if Og.thread_safe @pool = Pool.new ([:connection_count] || 5).times do @pool << @store_class.new(@options) @pool.last.ogmanager = self end else @store = @store_class.new(@options) @store.ogmanager = self end end |
#load(options = {}) ⇒ Object Also known as: import
Load Og managed objects from the filesystem. This method can apply optional transformation rules in order to evolve a schema.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/og/dump.rb', line 31 def load( = {}) classes = [:classes] || manageable_classes basedir = [:basedir] || 'ogdump' rules = [:rules] || rules[:evolution] || {} classes.each { |c| c.destroy if managed?(c) } unmanage_classes(classes) manage_classes for f in Dir["#{basedir}/*.yml"] all = YAML.load(File.read(f)) unless all.empty? klass = f.split(/\/|\./)[1] Logger.info "Loading class '#{klass}'" if krules = rules[klass.to_sym] if krules[:self] # Class name changed. Logger.info "Renaming class '#{klass}' to '#{krules[:self]}'" klass = krules[:self] end Logger.info "Evolution transformation will be applied!" end klass = constant(klass) for h in all obj = klass.allocate obj.assign_with(h) if krules krules.each do |old, new| obj.instance_variable_set "@#{new}", h[old] end end obj.insert end end end end |
#manage(klass) ⇒ Object
Manage a class. Converts the class to an Entity.
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/og/manager.rb', line 171 def manage(klass) return if managed?(klass) or (!manageable?(klass)) info = EntityInfo.new(klass) # Check if the class has a :text key. for a in klass.serializable_attributes anno = klass.ann(a) if anno[:key] klass.ann.self[:text_key] = a break end end # DON'T DO THIS!!! #-- # gmosx: this is used though, dont remove without recoding # some stuff. #++ klass.module_eval %{ def ==(other) other.instance_of?(#{klass}) ? @#{klass.primary_key} == other.#{klass.primary_key} : false end } klass.class.send(:attr_accessor, :ogmanager) klass.instance_variable_set '@ogmanager', self # FIXME: move somewhere else. klass.define_force_methods Relation.enchant(klass) # ensure that the superclass is managed before the # subclass. manage(klass.superclass) if manageable?(klass.superclass) # Perform store related enchanting. store.enchant(klass, self); put_store # Call special class enchanting code. klass.enchant if klass.respond_to?(:enchant) @entities[klass] = info end |
#manage_classes(*classes) ⇒ Object Also known as: manage_class
Manage a collection of classes.
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'lib/og/manager.rb', line 268 def manage_classes(*classes) classes.flatten! classes.compact! mc = self.class.managed_classes classes = manageable_classes.flatten if classes.empty? classes = classes.reject { |c| mc.member?(c) || !manageable?(c) } sc = @store_class.allocate classes.each { |c| sc.force_primary_key(c) } classes.each { |c| Relation.resolve_targets(c) } classes.each { |c| Relation.resolve_polymorphic_markers(c) } # The polymorpic resolution step creates more manageable classes. classes += classes.map {|c| Relation.resolve_polymorphic_relations(c) } classes.flatten! classes = classes.reject { |c| !c or self.class.managed?(c) } Logger.debug "Og manageable classes: #{classes.inspect}" if $DBG classes.each { |c| Relation.resolve_targets(c) } classes.each { |c| Relation.resolve_names(c) } classes.each { |c| manage(c) } end |
#manageable?(klass) ⇒ Boolean
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)
230 231 232 233 234 235 |
# File 'lib/og/manager.rb', line 230 def manageable?(klass) (klass.respond_to?(:serializable_attributes)) and (!klass.serializable_attributes.empty?) and (!Og.unmanageable_classes.include?(klass)) and (!klass.polymorphic_parent?) end |
#manageable_classes ⇒ Object
Use Ruby’s advanced reflection features to find all manageable classes. Managable are all classes that define Properties.
254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/og/manager.rb', line 254 def manageable_classes classes = [] ObjectSpace.each_object(Class) do |c| if manageable?(c) classes << c end end return classes end |
#managed?(klass) ⇒ Boolean Also known as: entity?
Is the class managed by Og?
239 240 241 |
# File 'lib/og/manager.rb', line 239 def managed?(klass) @entities.include?(klass) end |
#managed_classes ⇒ Object
Returns an array containing all classes managed by this manager.
246 247 248 |
# File 'lib/og/manager.rb', line 246 def managed_classes @entities.map {|e| e[0]} end |
#post_setup ⇒ Object
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.
319 320 321 |
# File 'lib/og/manager.rb', line 319 def post_setup store.post_setup if store.respond_to?(:post_setup) end |
#put_store ⇒ Object
Return a store to the pool.
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/og/manager.rb', line 146 def put_store if @pool thread = Thread.current if conn = thread[:og_store] # store released to the wrong manager? if conn.ogmanager != self return conn.ogmanager.put_store end thread[:og_store] = nil return @pool.push(conn) end end end |
#resolve_polymorphic(klass) ⇒ Object
Resolve polymorphic relations.
165 166 167 |
# File 'lib/og/manager.rb', line 165 def resolve_polymorphic(klass) Relations.resolve_polymorphic(klass) end |
#unmanage_classes(*classes) ⇒ Object Also known as: unmanage_class
Do not manage the given classes.
301 302 303 304 305 306 307 |
# File 'lib/og/manager.rb', line 301 def unmanage_classes(*classes) classes = manageable_classes.flatten if classes.empty? for c in classes @entities.delete_if { |k, v| v.klass == c } end end |