app/models/service_store.rb in umlaut-3.0.5 vs app/models/service_store.rb in umlaut-3.1.0.pre1

- old
+ new

@@ -1,63 +1,132 @@ -# Loads Service definitions from Rails.root/config/umlaut_services.yml -# instantiates services from definitions, by id. +# A ServiceStore is a collection of umlaut service definitions, with identifiers. # -# It's terrible we need to do this globally like this, but -# too hard to back out of legacy design now. +# There is one default global one that is typically used; originally this +# was all neccesarily global state, but we refactored to be an actual object, +# although there's still a default global one used, with class methods +# that delegate to it, for backwards compat and convenience. +# +# By default, a ServiceStore loads service definitions from +# Rails.root/config/umlaut_services.yml . Although in testing, +# or for future architectural expansion, services can be manually supplied +# instead. +# +# A ServiceStore instantiates services from definitions, by id, +# ServiceStore.instantiate_service!("our_sfx") +# +# A ServiceStore's cached service definitions can be reset, useful in +# testing: ServiceStore.reset! +# +# They'll then be lazily reloaded on next access, unless manually set. class ServiceStore - + @@global_service_store = ServiceStore.new + def self.global_service_store + @@global_service_store + end + + # certain class methods all default to global default ServiceStore, + # for global ServiceStore. For convenience, and backwards-compat. + [ :config, :"config=", :service_definitions, :service_definition_for, + :'instantiate_service!', :'reset!' ].each do |method| + self.define_singleton_method(method) do |*args| + global_service_store.send(method, *args) + end + end + + # Returns complete hash loaded from services.yml - def self.config - # cache hash loaded from YAML, ensure it has the keys we expect. - unless defined? @@services_config_list + def config + # cache hash loaded from YAML, ensure it has the keys we expect. + unless defined? @services_config_list yaml_path = File.expand_path("config/umlaut_services.yml", Rails.root) - if File.exists? yaml_path - @@services_config_list = YAML::load(File.open( yaml_path )) - else - @@services_config_list = {} - end - @@services_config_list["default"] ||= {} - @@services_config_list["default"]["services"] ||= {} + @services_config_list = (File.exists? yaml_path) ? YAML::load(File.open(yaml_path)) : {} + @services_config_list["default"] ||= {} + @services_config_list["default"]["services"] ||= {} end - return @@services_config_list + return @services_config_list end - + + # Manually set a config hash, as would normally be found serialized + # in config/umlaut_services.yml. Useful in testing. All keys + # should be strings!! + # + # Needs to have the somewhat cumbersome expected structure: + # ["default"]["services"] => { "service_id" => definition_hash } + def config=(hash) + reset! + @services_config_list = hash + end + # Returns hash keyed by unique service name, value service definition - # hash. - def self.service_definitions - unless defined? @@service_definitions - @@service_definitions = {} + # hash. + def service_definitions + unless defined? @service_definitions + @service_definitions = {} config.each_pair do |group_name, group| - @@service_definitions.merge!( group["services"] ) if group["services"] + if group["services"] + # Add the group name to each service + # in the group + group["services"].each_pair do |service_id, service| + service["group"] = group_name + end + # Merge the group's services into the service definitions. + @service_definitions.merge!( group["services"] ) + end end # set service_id key in each based on hash key - @@service_definitions.each_pair do |key, hash| + @service_definitions.each_pair do |key, hash| hash["service_id"] = key end end - return @@service_definitions + return @service_definitions end - - def self.service_definition_for(service_id) + + # Reset cached service definitions. They'll be lazily loaded when asked for, + # typically by being looked up from disk again. Typically used for testing. + def reset! + remove_instance_variable "@service_definitions" if defined? @service_definitions + remove_instance_variable "@services_config_list" if defined? @services_config_list + end + + def service_definition_for(service_id) return service_definitions[service_id] end - - # pass in string unique key OR a service definition hash, + + # pass in array of service group ids. eg. ["group1", "-group2"] + # + # Returns a list of service definition hashes. + # + # Start with default group(s). Remove any that are mentioned with "-group_id" in + # the group list, add in any that are mentioned with "group_id" + def determine_services(specified_groups = []) + services = {} + + activated_service_groups = self.config.select do |group_id, group_definition| + ((group_id == "default" || group_definition["default"] == true) || + specified_groups.include?(group_id)) && + ! specified_groups.include?("-#{group_id}") + end + + activated_service_groups.each_pair do |group_id, group_definition| + services.merge! (group_definition["services"] || {}) + end + + # Remove any disabled services + services.reject! {|service_id, hash| hash && hash["disabled"] == true} + + return services + end + + + # pass in string unique key OR a service definition hash, # and a current UmlautRequest. - # get back instantiated Service object. - def self.instantiate_service!(service, request) + # get back instantiated Service object. + def instantiate_service!(service, request) definition = service.kind_of?(Hash) ? service : service_definition_for(service.to_s) - - if definition.nil? - raise "Service '#{service}'' does not exist in umlaut-services.yml" - end - + raise "Service '#{service}'' does not exist in umlaut-services.yml" if definition.nil? className = definition["type"] || definition["service_id"] classConst = Kernel.const_get(className) service = classConst.new(definition) service.request = request - - return service + return service end - - end