-
Notifications
You must be signed in to change notification settings - Fork 18
/
canable.rb
82 lines (70 loc) · 2.13 KB
/
canable.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
module Canable
# Module that holds all the can_action? methods.
module Cans; end
# Module that holds all the [method]able_by? methods.
module Ables; end
# Module that holds all the enforce_[action]_permission methods for use in controllers.
module Enforcers
def self.included(controller)
controller.class_eval do
Canable.cans.each do |can|
helper_method "can_#{can}?" if controller.respond_to?(:helper_method)
hide_action "can_#{can}?" if controller.respond_to?(:hide_action)
end
end
end
end
# Exception that gets raised when permissions are broken for whatever reason.
class Transgression < StandardError; end
# Default actions to an empty hash.
@actions = {}
# Returns hash of actions that have been added.
# {:view => :viewable, ...}
def self.actions
@actions
end
def self.cans
actions.keys
end
# Adds an action to actions and the correct methods to can and able modules.
#
# @param [Symbol] can_method The name of the can_[action]? method.
# @param [Symbol] resource_method The name of the [resource_method]_by? method.
def self.add(can, able)
@actions[can] = able
add_can_method(can, able)
add_able_method(able)
add_enforcer_method(can)
end
private
def self.add_can_method(can, able)
Cans.module_eval <<-EOM
def can_#{can}?(resource)
return false if resource.blank?
resource.#{able}_by?(self)
end
EOM
end
def self.add_able_method(able)
Ables.module_eval <<-EOM
def #{able}_by?(user)
true
end
EOM
end
def self.add_enforcer_method(can)
Enforcers.module_eval <<-EOM
def can_#{can}?(resource)
current_user && current_user.can_#{can}?(resource)
end
def enforce_#{can}_permission(resource, message="")
raise(Canable::Transgression, message) unless can_#{can}?(resource)
end
private :enforce_#{can}_permission
EOM
end
end
Canable.add(:view, :viewable)
Canable.add(:create, :creatable)
Canable.add(:update, :updatable)
Canable.add(:destroy, :destroyable)