require 'ohm' require 'ohm/contrib' require 'guid' module Noah class Model < Ohm::Model def self.inherited(model) model.send :include, Ohm::Timestamping model.send :include, Ohm::Typecast model.send :include, Ohm::Callbacks model.send :include, Ohm::ExtraValidations model.send :attribute, :metadata # removing this as it's simply redundant # model.after :save, :notify_via_redis_save model.after :create, :notify_via_redis_create model.after :update, :notify_via_redis_update model.before :delete, :stash_name model.after :delete, :notify_via_redis_delete model.send :include, ModelClassMethods end end module ModelClassMethods def self.included(base) Noah::RegisteredModels.register_model(base) end def is_new? self.created_at == self.updated_at end def link!(path) base_pattern = "#{self.patternize_me}" path.nil? ? (raise ArgumentError, "Must provide a path") : p=path begin l = Link.find_or_create :path => p l.nodes = self rescue Exception => e e.message end end def watch!(opts={:endpoint => nil}) base_pattern = "#{self.patternize_me}" opts[:endpoint].nil? ? (raise ArgumentError, "Need an endpoint") : endpoint=opts[:endpoint] begin w = Watcher.new :pattern => base_pattern, :endpoint => endpoint w.valid? ? w.save : (raise "#{w.errors}") w.name rescue Exception => e e.message end end protected def patternize_me(opts = {:namespace => nil}) opts[:namespace].nil? ? namespace="//noah/#{self.class_to_lower}s" : namespace="//noah/#{opts[:namespace]}/#{self.class_to_lower}s" name.match(/^\//) ? n = name.gsub(/^\//, '') : n = name "#{namespace}/#{n}" end def stash_name @deleted_name = self.name end def class_to_lower(class_name = self.class.to_s) class_name.gsub(/(.*)::(\w)/,'\2').downcase end def dbnum o = Ohm.options.first return "0" if o.nil? return "0" if (o[:db].nil? && o[:url].nil?) o[:db].nil? ? "#{o[:url].split('/').last}" : "#{o[:db]}" end ["create", "update", "delete"].each do |meth| class_eval do define_method("notify_via_redis_#{meth}".to_sym) do db = self.dbnum self.name.nil? ? name=@deleted_name : name=self.name # Pulling out dbnum for now. Need to rethink it #pub_category = "#{db}:noah.#{self.class.to_s}[#{name}].#{meth}" pub_category = "#{self.patternize_me}" Ohm.redis.publish(pub_category, self.to_hash.merge({"action" => meth, "pubcategory" => pub_category}).to_json) # The following provides a post post-action hook. It allows a class to provide it's own handling after the fact # good example is in [Noah::Ephemeral] where it's used to check for/clean up expired ephemeral nodes entries self.send("#{meth}_hook".to_sym) unless self.protected_methods.member?("#{meth}_hook".to_sym) == false end end end private def initialize_id @id ||= Guid.new.to_s end end class RegisteredModels @@models = [] def self.register_model(model) @@models << model end def self.models @@models end end end require File.join(File.dirname(__FILE__), 'linkable') require File.join(File.dirname(__FILE__), 'models','link') require File.join(File.dirname(__FILE__), 'taggable') require File.join(File.dirname(__FILE__), 'models','tags') require File.join(File.dirname(__FILE__), 'models','link') require File.join(File.dirname(__FILE__), 'models','hosts') require File.join(File.dirname(__FILE__), 'models','services') require File.join(File.dirname(__FILE__), 'models','applications') require File.join(File.dirname(__FILE__), 'models','configurations') require File.join(File.dirname(__FILE__), 'models','watchers') require File.join(File.dirname(__FILE__), 'models','ephemerals')