Module: Dry::Ability

Extended by:
ActiveSupport::Concern, DSL
Defined in:
lib/dry/ability.rb,
lib/dry/ability/f.rb,
lib/dry/ability/t.rb,
lib/dry/ability/key.rb,
lib/dry/ability/rule.rb,
lib/dry/ability/version.rb,
lib/dry/ability/container.rb,
lib/dry/ability/controller.rb,
lib/dry/ability/exceptions.rb,
lib/dry/ability/rules_builder.rb,
lib/dry/ability/controller/dsl.rb,
lib/dry/ability/rule_interface.rb,
lib/dry/ability/controller/mixin.rb,
lib/dry/ability/resource_mediator.rb,
lib/dry/ability/inherited_resource.rb,
lib/dry/ability/controller/resource.rb,
lib/dry/ability/controller_resource.rb

Overview

Mixin class with DSL to define abilities

Examples:


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

Defined Under Namespace

Modules: ClassMethods, Controller, DSL, F, RuleInterface, T Classes: AccessDenied, AuthorizationNotPerformed, Container, ControllerResource, Error, InheritedResource, Key, ResourceMediator, Rule, RuleNotDefined, RulesBuilder, ScopeNotDefault

Constant Summary collapse

VERSION =
'0.0.3'

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from DSL

define

Instance Attribute Details

#accountObject (readonly)

Returns the value of attribute account.



53
54
55
# File 'lib/dry/ability.rb', line 53

def 
  @account
end

Instance Method Details

#attributes_for(action, subject) ⇒ Object



81
82
83
84
85
86
87
88
# 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

#authorize!(action, subject, message: nil) ⇒ Object



59
60
61
62
63
64
65
# File 'lib/dry/ability.rb', line 59

def authorize!(action, subject, message: nil)
  if can?(action, subject)
    subject
  else
    raise AccessDenied.new(message, action, subject)
  end
end

#can?(action, subject) ⇒ Boolean

Returns:

  • (Boolean)


67
68
69
70
71
72
73
74
75
# 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) ⇒ Boolean

Returns:

  • (Boolean)


77
78
79
# File 'lib/dry/ability.rb', line 77

def cannot?(action, subject, *args)
  !can?(action, subject, *args)
end

#initialize(account) ⇒ Object



55
56
57
# File 'lib/dry/ability.rb', line 55

def initialize()
  @account = 
end

#resolve_rules(action, subject) ⇒ Object



109
110
111
112
113
114
# 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

#scope_for(action, subject) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# 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