lib/zendesk_api/association.rb in zendesk_api-0.1.7 vs lib/zendesk_api/association.rb in zendesk_api-0.1.8

- old
+ new

@@ -1,9 +1,10 @@ require 'zendesk_api/helpers' module ZendeskAPI # Represents an association between two resources + # @private class Association # @return [Hash] Options passed into the association attr_reader :options # Options to pass in @@ -33,11 +34,11 @@ namespace = @options[:class].to_s.split("::") namespace.delete("ZendeskAPI") has_parent = namespace.size > 1 || (options[:with_parent] && @options.parent) if has_parent - parent_class = @options.parent ? @options.parent.class : ZendeskAPI.get_class(namespace[0]) + parent_class = @options.parent ? @options.parent.class : ZendeskAPI.const_get(ZendeskAPI::Helpers.modulize_string(namespace[0])) parent_namespace = build_parent_namespace(parent_class, instance, options, original_options) namespace[1..1] = parent_namespace if parent_namespace namespace[0] = parent_class.resource_name else namespace[0] = @options.path || @options[:class].resource_name @@ -48,10 +49,11 @@ end namespace.join("/") end + # Tries to place side loads onto given resources. def side_load(resources, side_loads) key = "#{options.name}_id" plural_key = "#{Inflection.singular options.name.to_s}_ids" resources.each do |resource| @@ -136,10 +138,12 @@ # This module holds association method for resources. # Associations can be loaded in three ways: # * Commonly used resources are automatically side-loaded server side and sent along with their parent object. # * Associated resource ids are sent and are then loaded one-by-one into the parent collection. # * The association is represented with Rails' nested association urls (such as tickets/:id/groups) and are loaded that way. + # + # @private module Associations def self.included(base) base.send(:extend, ClassMethods) end @@ -154,10 +158,11 @@ resource.association = instance_association resource end end + # @private module ClassMethods include Rescue def associations @associations ||= [] @@ -172,14 +177,19 @@ associated_with end end # Represents a parent-to-child association between resources. Options to pass in are: class, path. - # @param [Symbol] resource_name The underlying resource name - # @param [Hash] opts The options to pass to the method definition. - def has(resource_name, class_level_options = {}) - klass = get_class(class_level_options.delete(:class)) || get_class(resource_name) + # @param [Symbol] resource_name_or_class The underlying resource name or a class to get it from + # @param [Hash] class_level_options The options to pass to the method definition. + def has(resource_name_or_class, class_level_options = {}) + if klass = class_level_options.delete(:class) + resource_name = resource_name_or_class + else + klass = resource_name_or_class + resource_name = klass.singular_resource_name + end class_level_association = { :class => klass, :name => resource_name, :inline => class_level_options.delete(:inline), @@ -227,22 +237,27 @@ instance_variable_set("@#{resource_name}", resource) end end # Represents a parent-to-children association between resources. Options to pass in are: class, path. - # @param [Symbol] resource The underlying resource name - # @param [Hash] opts The options to pass to the method definition. - def has_many(resource_name, class_level_opts = {}) - klass = get_class(class_level_opts.delete(:class)) || get_class(Inflection.singular(resource_name.to_s)) + # @param [Symbol] resource_name_or_class The underlying resource name or class to get it from + # @param [Hash] class_level_options The options to pass to the method definition. + def has_many(resource_name_or_class, class_level_options = {}) + if klass = class_level_options.delete(:class) + resource_name = resource_name_or_class + else + klass = resource_name_or_class + resource_name = klass.resource_name + end class_level_association = { :class => klass, :name => resource_name, - :inline => class_level_opts.delete(:inline), - :path => class_level_opts.delete(:path), - :include => (class_level_opts.delete(:include) || klass.resource_name).to_s, - :include_key => (class_level_opts.delete(:include_key) || :id).to_s, + :inline => class_level_options.delete(:inline), + :path => class_level_options.delete(:path), + :include => (class_level_options.delete(:include) || klass.resource_name).to_s, + :include_key => (class_level_options.delete(:include_key) || :id).to_s, :singular => false } associations << class_level_association @@ -289,50 +304,9 @@ end send("#{id_column}=", resources.map(&:id)) if resources && has_key?(id_column) resource end - end - - # Allows using has and has_many without having class defined yet - # Guesses at Resource, if it's anything else and the class is later - # reopened under a different superclass, an error will be thrown - def get_class(resource) - return false if resource.nil? - res = ZendeskAPI::Helpers.modulize_string(resource.to_s) - - begin - const_get(res) - rescue NameError, ArgumentError # ruby raises NameError, rails raises ArgumentError - ZendeskAPI.get_class(resource) - end - end - end - end - - class << self - # Make sure Rails' overwriting of const_missing doesn't cause trouble - def const_missing(*args) - Object.const_missing(*args) - end - - # Allows using has and has_many without having class defined yet - # Guesses at Resource, if it's anything else and the class is later - # reopened under a different superclass, an error will be thrown - def get_class(resource) - return false if resource.nil? - res = ZendeskAPI::Helpers.modulize_string(resource.to_s).split("::") - - begin - res[1..-1].inject(ZendeskAPI.const_get(res[0])) do |iter, k| - begin - iter.const_get(k) - rescue - iter.const_set(k, Class.new(Resource)) - end - end - rescue NameError - ZendeskAPI.const_set(res[0], Class.new(Resource)) end end end end