lib/zendesk_api/association.rb in zendesk_api-0.2.5 vs lib/zendesk_api/association.rb in zendesk_api-0.2.6

- old
+ new

@@ -56,38 +56,15 @@ key = "#{options.name}_id" plural_key = "#{Inflection.singular options.name.to_s}_ids" resources.each do |resource| if resource.key?(plural_key) # Grab associations from child_ids field on resource - ids = resource.send(plural_key) - - resource.send("#{options.name}=", _side_load(resource, side_loads.select {|side_load| - ids.include?(side_load[options.include_key]) - })) + side_load_from_child_ids(resource, side_loads, plural_key) elsif resource.key?(key) || options.singular - # Either grab association from child_id field on resource or parent_id on child resource - if resource.key?(key) - id = resource.send(key) - include_key = options.include_key - else - id = resource.id - include_key = "#{resource.class.singular_resource_name}_id" - end - - next unless id - - side_load = side_loads.detect do |side_load| - id == side_load[include_key] - end - - resource.send("#{options.name}=", side_load) if side_load + side_load_from_child_or_parent_id(resource, side_loads, key) else # Grab associations from parent_id field from multiple child resources - key = "#{resource.class.singular_resource_name}_id" - - resource.send("#{options.name}=", _side_load(resource, side_loads.select {|side_load| - side_load[key] == resource.id - })) + side_load_from_parent_id(resource, side_loads, key) end end end private @@ -100,10 +77,45 @@ ZendeskAPI::Collection.new(resource.client, options[:class]).tap do |collection| collection.replace(side_loads) end end + def side_load_from_parent_id(resource, side_loads, key) + key = "#{resource.class.singular_resource_name}_id" + + resource.send("#{options.name}=", _side_load(resource, side_loads.select {|side_load| + side_load[key] == resource.id + })) + end + + def side_load_from_child_ids(resource, side_loads, plural_key) + ids = resource.send(plural_key) + + resource.send("#{options.name}=", _side_load(resource, side_loads.select {|side_load| + ids.include?(side_load[options.include_key]) + })) + end + + def side_load_from_child_or_parent_id(resource, side_loads, key) + # Either grab association from child_id field on resource or parent_id on child resource + if resource.key?(key) + id = resource.send(key) + include_key = options.include_key + else + id = resource.id + include_key = "#{resource.class.singular_resource_name}_id" + end + + return unless id + + side_load = side_loads.detect do |side_load| + id == side_load[include_key] + end + + resource.send("#{options.name}=", side_load) if side_load + end + def build_parent_namespace(parent_class, instance, options, original_options) return unless association_on_parent = parent_class.associations.detect {|a| a[:class] == @options[:class] } [ extract_parent_id(parent_class, instance, options, original_options), @options.path || association_on_parent[:name].to_s @@ -128,184 +140,9 @@ if options[:with_id] && !@options[:class].ancestors.include?(SingularResource) if instance && instance.id instance.id elsif options[:id] original_options.delete(:id) || original_options.delete("id") - end - end - end - end - - # 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 - - def wrap_resource(resource, klass, class_level_association) - instance_association = Association.new(class_level_association.merge(:parent => self)) - case resource - when Hash - klass.new(@client, resource.merge(:association => instance_association)) - when String, Fixnum - klass.new(@client, :id => resource, :association => instance_association) - else - resource.association = instance_association - resource - end - end - - # @private - module ClassMethods - include Rescue - - def associations - @associations ||= [] - end - - def associated_with(name) - associations.inject([]) do |associated_with, association| - if association[:include] == name.to_s - associated_with.push(Association.new(association)) - end - - associated_with - end - end - - # Represents a parent-to-child association between resources. Options to pass in are: class, path. - # @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), - :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 => true - } - - associations << class_level_association - - id_column = "#{resource_name}_id" - - define_method "#{resource_name}_used?" do - !!instance_variable_get("@#{resource_name}") - end - - define_method resource_name do |*args| - instance_options = args.last.is_a?(Hash) ? args.pop : {} - - # return if cached - cached = instance_variable_get("@#{resource_name}") - return cached if cached && !instance_options[:reload] - - # find and cache association - instance_association = Association.new(class_level_association.merge(:parent => self)) - resource = if klass.respond_to?(:find) && resource_id = method_missing(id_column) - klass.find(@client, :id => resource_id, :association => instance_association) - elsif found = method_missing(resource_name.to_sym) - wrap_resource(found, klass, class_level_association) - elsif klass.superclass == DataResource - rescue_client_error do - response = @client.connection.get(instance_association.generate_path(:with_parent => true)) - klass.new(@client, response.body[klass.singular_resource_name].merge(:association => instance_association)) - end - end - - send("#{id_column}=", resource.id) if resource && has_key?(id_column) - instance_variable_set("@#{resource_name}", resource) - end - - define_method "#{resource_name}=" do |resource| - resource = wrap_resource(resource, klass, class_level_association) - send("#{id_column}=", resource.id) if has_key?(id_column) - 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_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_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 - - id_column = "#{resource_name}_ids" - - define_method "#{resource_name}_used?" do - !!instance_variable_get("@#{resource_name}") - end - - define_method resource_name do |*args| - instance_opts = args.last.is_a?(Hash) ? args.pop : {} - - # return if cached - cached = instance_variable_get("@#{resource_name}") - return cached if cached && !instance_opts[:reload] - - # find and cache association - instance_association = Association.new(class_level_association.merge(:parent => self)) - singular_resource_name = Inflection.singular(resource_name.to_s) - - resources = if (ids = method_missing("#{singular_resource_name}_ids")) && ids.any? - ids.map do |id| - klass.find(@client, :id => id, :association => instance_association) - end.compact - elsif (resources = method_missing(resource_name.to_sym)) && resources.any? - resources.map do |res| - klass.new(@client, res.merge(:association => instance_association)) - end - else - ZendeskAPI::Collection.new(@client, klass, instance_opts.merge(:association => instance_association)) - end - - send("#{id_column}=", resources.map(&:id)) if resource && has_key?(id_column) - instance_variable_set("@#{resource_name}", resources) - end - - define_method "#{resource_name}=" do |resources| - if resources.is_a?(Array) - resources.map! { |attr| wrap_resource(attr, klass, class_level_association) } - send(resource_name).replace(resources) - else - resources.association = instance_association - instance_variable_set("@#{resource_name}", resources) - end - - send("#{id_column}=", resources.map(&:id)) if resources && has_key?(id_column) - resource end end end end end