lib/knj/objects.rb in knjrbfw-0.0.23 vs lib/knj/objects.rb in knjrbfw-0.0.24

- old
+ new

@@ -13,15 +13,13 @@ @args[:module] = Kernel if !@args[:module] @args[:cache] = :weak if !@args.key?(:cache) @objects = {} @locks = {} @data = {} - @mutex_require = Mutex.new + @lock_require = Monitor.new - if @args[:cache] == :weak - require "#{$knjpath}wref" - end + require "#{$knjpath}wref" if @args[:cache] == :weak @events = Knj::Event_handler.new @events.add_event( :name => :no_html, :connections_max => 1 @@ -32,10 +30,14 @@ ) @events.add_event( :name => :missing_class, :connections_max => 1 ) + @events.add_event( + :name => :require_class, + :connections_max => 1 + ) raise "No DB given." if !@args[:db] and !@args[:custom] raise "No class path given." if !@args[:class_path] and (@args[:require] or !@args.key?(:require)) if args[:require_all] @@ -70,10 +72,15 @@ end @locks[classname] = Mutex.new end + def uninit_class(classname) + @objects.delete(classname) + @locks.delete(classname) + end + #Returns a cloned version of the @objects variable. Cloned because iteration on it may crash some of the other methods in Ruby 1.9+ def objects objs_cloned = {} @objects.keys.each do |key| @@ -147,19 +154,35 @@ def requireclass(classname, args = {}) classname = classname.to_sym return false if @objects.key?(classname) - @mutex_require.synchronize do + @lock_require.synchronize do #Maybe the classname got required meanwhile the synchronized wait - check again. return false if @objects.key?(classname) - if (@args[:require] or !@args.key?(:require)) and (!args.key?(:require) or args[:require]) - filename = "#{@args[:class_path]}/#{@args[:class_pre]}#{classname.to_s.downcase}.rb" - filename_req = "#{@args[:class_path]}/#{@args[:class_pre]}#{classname.to_s.downcase}" - raise "Class file could not be found: #{filename}." if !File.exists?(filename) - require filename_req + if @events.connected?(:require_class) + @events.call(:require_class, { + :class => classname + }) + else + doreq = false + + if args[:require] + doreq = true + elsif args.key?(:require) and !args[:require] + doreq = false + elsif @args[:require] or !@args.key?(:require) + doreq = true + end + + if doreq + filename = "#{@args[:class_path]}/#{@args[:class_pre]}#{classname.to_s.downcase}.rb" + filename_req = "#{@args[:class_path]}/#{@args[:class_pre]}#{classname.to_s.downcase}" + raise "Class file could not be found: #{filename}." if !File.exists?(filename) + require filename_req + end end if args[:class] classob = args[:class] else @@ -225,11 +248,11 @@ self.requireclass(classname) if !@objects.key?(classname) @locks[classname].synchronize do #Maybe the object got spawned while we waited for the lock? If so we shouldnt spawn another instance. - if obj = @objects[classname].get!(id) and obj.id.to_i == id + if @args[:cache] == :weak and obj = @objects[classname].get!(id) and obj.id.to_i == id return obj end #Spawn object. if @args[:datarow] or @args[:custom] @@ -259,10 +282,11 @@ @objects[classname].delete(id) @objects_idclass.delete(id) end end + #Returns the first object found from the given arguments. Also automatically limits the results to 1. def get_by(classname, args = {}) classname = classname.to_sym self.requireclass(classname) classob = @args[:module].const_get(classname) @@ -342,10 +366,14 @@ if args[:addnew] or args[:add] html << "<option" html << " selected=\"selected\"" if !args[:selected] html << " value=\"\">#{_("Add new")}</option>" + elsif args[:none] + html << "<option" + html << " selected=\"selected\"" if !args[:selected] + html << " value=\"\">#{_("None")}</option>" end self.list(classname, args[:list_args]) do |object| html << "<option value=\"#{object.id.html}\"" @@ -459,10 +487,11 @@ end end #Add a new object to the database and to the cache. def add(classname, data = {}) + raise "data-variable was not a hash: '#{data.class.name}'." if !data.is_a?(Hash) classname = classname.to_sym self.requireclass(classname) if @args[:datarow] classobj = @args[:module].const_get(classname) @@ -592,10 +621,13 @@ @objects.delete(classname) end #Delete an object. Both from the database and from the cache. def delete(object) + #Return false if the object has already been deleted. + return false if object.deleted? + self.call("object" => object, "signal" => "delete_before") self.unset(object) obj_id = object.id object.delete if object.respond_to?(:delete) @@ -635,9 +667,10 @@ end else arr_ids = [] ids = [] objs.each do |obj| + next if obj.deleted? ids << obj.id if ids.length >= 1000 arr_ids << ids ids = [] end \ No newline at end of file