lib/api_resource/scopes.rb in api_resource-0.6.18 vs lib/api_resource/scopes.rb in api_resource-0.6.19

- old
+ new

@@ -1,20 +1,20 @@ module ApiResource module Scopes extend ActiveSupport::Concern - + module ClassMethods # TODO: calling these methods should force loading of the resource definition def scopes return self.related_objects[:scopes] end - + def scope?(name) self.related_objects[:scopes].has_key?(name.to_sym) end - + def scope_attributes(name) raise "No such scope #{name}" unless self.scope?(name) self.related_objects[:scopes][name.to_sym] end @@ -25,31 +25,31 @@ # @param scope_definition is always a hash with the arguments for the scope # e.g. {:page => "req", "per_page" => "opt"} def scope(scope_name, scope_definition) unless scope_definition.is_a?(Hash) - raise ArgumentError, "Expecting an attributes hash given #{scope_definition.inspect}" + raise ArgumentError, "Expecting an attributes hash given #{scope_definition.inspect}" end - + self.related_objects[:scopes][scope_name.to_sym] = scope_definition self.class_eval do define_singleton_method(scope_name) do |*args| - + arg_names = scope_definition.keys arg_types = scope_definition.values finder_opts = { scope_name => {} } arg_names.each_with_index do |arg_name, i| - + # If we are dealing with a scope with multiple args if arg_types[i] == :rest - finder_opts[scope_name][arg_name] = + finder_opts[scope_name][arg_name] = args.slice(i, args.count) # Else we are only dealing with a single argument else if arg_types[i] == :req || (i < args.count) finder_opts[scope_name][arg_name] = args[i] @@ -65,21 +65,79 @@ ApiResource::Conditions::ScopeCondition.new(finder_opts, self) end end end + + # + # Apply scopes from params based on our resource + # definition + # + def add_scopes(params, base = self) + # scopes are stored as strings but we want to allow + params = params.with_indifferent_access + base = self.add_static_scopes(params, base) + return self.add_dynamic_scopes(params, base) + end + + protected + + def add_static_scopes(params, base) + self.static_scopes.each do |name| + if params[name].present? + base = base.send(name) + end + end + return base + end + + def add_dynamic_scopes(params, base) + self.dynamic_scopes.each_pair do |name, args| + next if params[name].blank? + caller_args = [] + args.each_pair do |subkey, type| + if type == :req || params[name][subkey].present? + caller_args << params[name][subkey] + end + end + base = base.send(name, *caller_args) + end + return base + end + + # + # Wrapper method to define all scopes from the resource definition + # + # @return [Boolean] true + def define_all_scopes + if self.resource_definition["scopes"] + self.resource_definition["scopes"].each_pair do |name, opts| + self.scope(name, opts) + end + end + true + end + + def dynamic_scopes + self.scopes.select { |name, args| args.present? } + end + + def static_scopes + self.scopes.select { |name, args| args.blank? }.keys + end + end - + def scopes return self.class.scopes end - + def scope?(name) return self.class.scope?(name) end - + def scope_attributes(name) return self.class.scope_attributes(name) end - + end end