Skip to content

Instantly share code, notes, and snippets.

@AMHOL
Created April 6, 2013 22:07
Show Gist options
  • Save AMHOL/5327827 to your computer and use it in GitHub Desktop.
Save AMHOL/5327827 to your computer and use it in GitHub Desktop.
Library for building dependencies with ActiveResource
module ResourceHas
def self.included base
unless base.ancestors.include? InheritedResources::Base
raise '%s must inherit from InheritedResources::Base to implement ResourceHas' % base.name
end
base.extend(ClassMethods)
base.append_before_filter :__build_relations
end
## Class methods
module ClassMethods
def __get_resources
@resources ||= {}
end
def resource_has(*args, &block)
raise 'at least 2 arguments expected for resource_has (amount and relation name)' if args.length < 2
modifier = args.shift() unless args[0].is_a? Integer
amount = args.shift()
relation_name = args.shift()
self.__get_resources[relation_name] = {
:modifier => modifier,
:amount => amount,
:block => block,
:options => { :increment_by => amount, :on => %w(edit) }.merge(args.shift || {})
}
end
end
## Instance methods
protected
def __build_relations
self.class.__get_resources.each_pair do |relation_name, args|
return unless (args[:options][:only] || args[:options][:on]).include?(action_name)
__quantify(relation_name, args).times do
nested_resource = resource_method_chain __get_builder_method(relation_name)
args[:block].call(nested_resource) if args[:block]
end
end
end
def __quantify(relation_name, args)
return args[:options][:increment_by] unless args[:modifier]
quantifier = args[:amount] - resource.send(relation_name).try(:length).to_i
if args[:modifier].to_sym === :at_least
return args[:options][:increment_by] if quantifier < args[:options][:increment_by]
quantifier
elsif args[:modifier].to_sym === :at_most
return args[:options][:increment_by] if (quantifier + args[:options][:increment_by]) < args[:amount]
quantifier
end
end
def __get_builder_method(relation_name)
return 'build_%s' % relation_name if __get_single_relations.include?(resource.class.reflect_on_association(relation_name).macro)
return '%s.build' % relation_name
end
def resource_method_chain(method_chain)
return resource if method_chain.empty?
method_chain.split('.').flatten.inject(self.resource){ |object, method| object.send(method.to_sym) }
end
def __get_single_relations
[:has_one]
end
end
@AMHOL
Copy link
Author

AMHOL commented Apr 6, 2013

resource_has 3, :images, :increment_by => 3, :only => %w(edit)
resource_has :at_least, 3, :images, :increment_by => 1, :only => %w(edit)
resource_has :at_most, 3, :images, :increment_by => 3, :only => %w(edit)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment