module Dry::Ability
Mixin class with DSL
to define abilities
@example
class Ability include Dry::Ability.define -> do map_subject! :public => %w(Post Like Comment) map_action! :read => %i(index show), :create => %i(new), :update => %i(edit), :crud => %i(index create read show update destroy), :change => %i(update destroy) can :read, :public can : end end
Constants
- VERSION
Attributes
account[R]
Public Class Methods
new(account)
click to toggle source
# File lib/dry/ability.rb, line 55 def initialize(account) @account = account end
Public Instance Methods
accessible?()
click to toggle source
# File lib/dry/ability/rule.rb, line 55 def accessible? scope? || !@explicit_scope end
attributes_for(action, subject)
click to toggle source
# File lib/dry/ability.rb, line 81 def attributes_for(action, subject) rules = resolve_rules(action, subject) do return {} end rules.reduce({}) do |result, rule| result.merge!(rule.attributes_for(@account, subject)); result end end
before(controller)
click to toggle source
# File lib/dry/ability/resource_mediator.rb, line 72 def before(controller) resource_class(controller).new(self, controller).call end
call(account, object)
click to toggle source
# File lib/dry/ability/rule.rb, line 22 def call(account, object) if filter? filter.(account, object) else @constraints.blank? || run_constraints(account, object, @constraints) end ^ @inverse end
can?(action, subject)
click to toggle source
# File lib/dry/ability.rb, line 67 def can?(action, subject) rules = resolve_rules(action, subject) do return false end rules.reduce(true) do |result, rule| result && rule[@account, subject] end end
cannot?(action, subject, *args)
click to toggle source
# File lib/dry/ability.rb, line 77 def cannot?(action, subject, *args) !can?(action, subject, *args) end
collection_action?(action_name, *)
click to toggle source
# File lib/dry/ability/resource_mediator.rb, line 89 def collection_action?(action_name, *) @collection_actions.include?(action_name) end
filter?()
click to toggle source
# File lib/dry/ability/rule.rb, line 47 def filter? !@filter.nil? end
member_action?(action_name, params)
click to toggle source
# File lib/dry/ability/resource_mediator.rb, line 84 def member_action?(action_name, params) @new_actions.include?(action_name) || singleton? || ((params[:id] || params[@id_param_key]) && !@collection_actions.include?(action_name)) end
register_to(_rules)
click to toggle source
# File lib/dry/ability/rule.rb, line 59 def register_to(_rules) unless defined?(@_registered) @subjects.each do |subject| _rules.namespace(subject) do |_subject| @actions.each do |action| key = _subject.send(:namespaced, action) pred = _rules._container.delete(key)&.call rules_or = pred | self if pred _subject.register action, (rules_or || self) end end end @_registered = true end end
resolve_rules(action, subject) { |: nil| ... }
click to toggle source
# File lib/dry/ability.rb, line 109 def resolve_rules(action, subject) rules.resolve_with_mappings(action, subject) do |e| Rails.logger.warn { e.message } block_given? ? yield : nil end end
resource_class(controller)
click to toggle source
# File lib/dry/ability/resource_mediator.rb, line 76 def resource_class(controller) if defined?(::InheritedResources) && controller.is_a?(::InheritedResources::Actions) InheritedResource else ControllerResource end end
scope?()
click to toggle source
# File lib/dry/ability/rule.rb, line 51 def scope? !@scope.nil? end
scope_for(action, subject) { || ... }
click to toggle source
# File lib/dry/ability.rb, line 90 def scope_for(action, subject) rules = resolve_rules(action, subject) do return yield if block_given? if subject.respond_to?(:none) return subject.none else raise ArgumentError, "expected subject to be an ActiveRecord::Base class or Relation. given: #{subject}" end end if rules.none?(&:accessible?) if block_given? return yield else raise Error, "none of matched rules are provides scope for #{action}, #{subject}, pass block instead" end end rules.map { |rule| rule.scope_for(@account, subject) }.reduce(:merge) end
|(other)
click to toggle source
# File lib/dry/ability/rule.rb, line 75 def |(other) Or.new([self, other]) end
Private Instance Methods
call_constraint(account, object, key, constraint)
click to toggle source
# File lib/dry/ability/rule.rb, line 126 def call_constraint(account, object, key, constraint) value = object.public_send(key) case constraint when Array constraint.include?(value) when Hash run_constraints(account, value, constraint) when Proc constraint.arity > 1 ? constraint.(account, value) : value == constraint.(account) else value == constraint end end
run_constraints(account, object, dict)
click to toggle source
# File lib/dry/ability/rule.rb, line 116 def run_constraints(account, object, dict) case object when Class, Symbol true else dict.reduce(true) do |pred, (key, value)| pred && call_constraint(account, object, key, value) end end end