Skip to content

Instantly share code, notes, and snippets.

@mattconnolly
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattconnolly/9043398 to your computer and use it in GitHub Desktop.
Save mattconnolly/9043398 to your computer and use it in GitHub Desktop.
A module with code to hierarchically load and authorise resources in a before_filter.
module NestedLoadAndAuthorize
def load_and_authorize(name, options={})
@_through_stack ||= []
# only touch can can if the instance variable is nil
resource = instance_variable_get("@#{name}")
if resource.nil?
# apply if, only and except behaviours just is if this was done by before_filter
proceed = true
proceed &&= [*options[:only]].include?(action_name.to_sym) if options[:only]
proceed &&= ![*options[:except]].include?(action_name.to_sym) if options[:except]
proceed &&= case options[:if]
when Symbol
send(options[:if])
when Proc
options[:if].call
when nil
true
end
if proceed
# automatically load this resource through a nested one unless manually specified
options[:through] = @_through_stack.last unless @_through_stack.empty? || options.include?(:through)
# create the can can resource class
cancan = self.class.cancan_resource_class.new(self, name, options.except(:if, :only, :except, :param))
resource = cancan.load_resource
cancan.authorize_resource unless options[:skip_authorize]
if resource && block_given?
# only call block if we got an instance variable set
begin
@_through_stack.push(name)
yield
ensure
@_through_stack.pop
end
end
end
end
resource
end
# load and authorise a resource only if the param is present.
def load_and_authorize_if_present(name, options={}, &block)
key = options[:id_param] || "#{name}_id"
if params[key]
load_and_authorize(name, options, &block)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment