Skip to content

Instantly share code, notes, and snippets.

@xeviknal
Last active December 23, 2015 12:59
Show Gist options
  • Save xeviknal/a0ba1f4ff022b99b69fe to your computer and use it in GitHub Desktop.
Save xeviknal/a0ba1f4ff022b99b69fe to your computer and use it in GitHub Desktop.
Monkey patching can method in order to reach evaluated permissions in a block
module Admin::CacheHelper
def cache_with_permissions(name=[], options = nil, &cache_block)
permission_version = options && options[:permission_version] || :v0
permission_required = get_cache_key_for(name, permission_version, &cache_block)
name = name + permission_required
cache(name, options) { cache_block.call }
end
def get_cache_key_for(fragment_key, version, &cache_block)
permission_required = Camaloon::Cache::PermissionGatherer.gather([ :permission_version, version ] << fragment_key, cache_block)
permission_required.collect do |action, subject, extra_args|
[action, subject, current_ability.can?(action, subject, extra_args)].join "-"
end
end
end
- cache_with_permissions([@order, I18n.locale]) do
h1 Ola
- if can?(:create, Design)
= render 'form'
user:
create_design? yes / no
...
def cache_with_permissions(keys, &block)
permisos_necesaris = Camaloon.cache.fetch("clau del tros") do
# Monkeypatch de can? i preparar el array per guardar els permissos
resultat = yield
@array_de_permisos_utilitzats
end
if resultat.nil?
cache(keys + permisos_necesaris(per curent user) do
yield
end
else
resultat
end
end
class PermissionGatherer
cattr_accessor :already_gathered
def self.gather(key, block)
if already_gathered
block.call
[]
else
Camaloon.cache(key) do
track_permissions(block) do
block.call
end
end
end
end
private
def self.track_permissions(cache_block, &block)
letting_recursivity do
klass = eval("self", cache_block.binding)
klass.class_eval do
attr_accessor :permissions
end
klass.instance_eval do
alias :can_without_register? :can?
self.permissions = []
@swap_output_buffer = @output_buffer
@output_buffer = ActionView::OutputBuffer.new
def can?(action, subject, *extra_args)
if get_class? subject
subject = subject.class
elsif current_ability.has_block?(action, subject)
raise RuntimeException, "not supported"
end
self.permissions << [action, subject, extra_args]
can_without_register?(action, subject, extra_args)
end
def get_class?(subject)
!( subject.is_a?(String) || subject.is_a?(Symbol) || subject.respond_to?(:ancestors) ) &&
subject.respond_to?(:class)
end
end
block.call
klass.instance_eval do
alias :can? :can_without_register?
undef :can_without_register?
@output_buffer = @swap_output_buffer
end
klass.instance_eval("self.permissions").uniq
end
end
def self.letting_recursivity(&block)
self.already_gathered = true
permissions = yield
self.already_gathered = false
permissions
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment