class Bali::Judge

Constants

DEFINITE_FALSE
DEFINITE_TRUE
FUZY_FALSE

Fuzy value is possible when the evaluation is not yet clear cut, for example in this case:

role :finance do

cant :view

end

others do

can :view
can :index

end

Checking cant view for finance role results in a definite false, but checking on index for the same role results in FUZY_TRUE. Eventually, all FUZY value will be normal TRUE or FALSE if no definite counterpart is found.

FUZY_TRUE

Attributes

actor[RW]
operation[RW]
record[RW]
role[RW]
should_cross_check[RW]
term[RW]

Public Class Methods

check(term, actor_or_roles, operation, record) click to toggle source
# File lib/bali/judge.rb, line 37
def check(term, actor_or_roles, operation, record)
  if operation.nil?
    # eg: user.can? :sign_in
    operation = actor_or_roles
    actor_or_roles = nil
  end

  judgement_value = default_value = default_judgement_value(term)
  roles = Bali::Role.formalize actor_or_roles

  roles.each do |role|
    judge = Bali::Judge.new(
      term: term,
      role: role,
      actor: actor_or_roles,
      operation: operation,
      record: record
    )

    judgement_value = judge.judgement
    break if judgement_value != default_value
  end

  judgement_value
end
default_judgement_value(term) click to toggle source
# File lib/bali/judge.rb, line 30
def default_judgement_value(term)
  case term
  when :can then false
  when :cant then true
  end
end
new(term:, actor:, role:, operation:, record:, should_cross_check: true) click to toggle source
# File lib/bali/judge.rb, line 64
def initialize(term:,
  actor:,
  role:,
  operation:,
  record:,
  should_cross_check: true)

  @term = term
  @role = role
  @actor = actor
  @operation = operation
  @record = record
  @should_cross_check = should_cross_check
end

Public Instance Methods

judgement() click to toggle source
# File lib/bali/judge.rb, line 79
def judgement
  judgement = natural_value if no_rule_group?

  if judgement.nil? && rule.nil?
    cross_check_value = nil
    # default if can? for undefined rule is false, after related clause
    # cant be found in cant?
    cross_check_value = cross_check_judge.judgement if should_cross_check

    # if cross check value nil, then the reverse rule is not defined,
    # let's determine whether they can do anything or not
    if cross_check_value.nil?
      judgement = deduce_from_defined_disposition
    else
      # process value from cross checking
      if otherly_rule && (cross_check_value == FUZY_FALSE || cross_check_value == FUZY_TRUE)
        # give chance to check at others block
        @rule = otherly_rule
      else
        judgement = reverse_value(cross_check_value)
      end
    end
  end

  judgement ||= deduce_by_evaluation ||
    deduce_from_fuzy_rules ||
    natural_value

  return !should_cross_check ?
    judgement :

    # translate response for value above to traditional true/false
    # holy judgement refer to non-standard true/false being used inside Bali
    # which need to be translated from other beings to know
    judgement > 0
end

Private Instance Methods

cross_check_judge() click to toggle source
# File lib/bali/judge.rb, line 151
def cross_check_judge
  @cross_check_judge ||= begin
    Bali::Judge.new(
      term: reversed_term,
      role: role,
      operation: operation,
      record: record,
      should_cross_check: false,
      actor: actor
    )
  end
end
deduce_by_evaluation() click to toggle source
# File lib/bali/judge.rb, line 195
def deduce_by_evaluation
  return unless rule

  rule.conditional? ?
    evaluate(rule, actor, record) :
    judgement = DEFINITE_TRUE
end
deduce_from_defined_disposition() click to toggle source
# File lib/bali/judge.rb, line 203
def deduce_from_defined_disposition
  return unless rule_group

  if rule_group.can_all?
    reverse_value(natural_value)
  elsif rule_group.cant_all?
    natural_value
  end
end
deduce_from_fuzy_rules() click to toggle source
# File lib/bali/judge.rb, line 213
def deduce_from_fuzy_rules
  reversed_otherly_rule = other_rule_group.find_rule(reversed_term, operation)

  if reversed_otherly_rule
    term == :cant ? FUZY_TRUE : FUZY_FALSE
  end
end
evaluate(rule, actor, record) click to toggle source
# File lib/bali/judge.rb, line 184
def evaluate(rule, actor, record)
  conditional = rule.conditional
  evaluation  = case conditional.arity
                when 0 then conditional.()
                when 1 then conditional.(record)
                when 2 then conditional.(record, actor)
                end

  evaluation ? DEFINITE_TRUE : DEFINITE_FALSE
end
natural_value() click to toggle source
# File lib/bali/judge.rb, line 171
def natural_value
  term == :cant ? DEFINITE_TRUE : DEFINITE_FALSE
end
no_rule_group?() click to toggle source
# File lib/bali/judge.rb, line 138
def no_rule_group?
  rule_group.nil? && other_rule_group.nil?
end
other_rule_group() click to toggle source
# File lib/bali/judge.rb, line 134
def other_rule_group
  @other_rule_group ||= rule_group_for nil
end
otherly_rule() click to toggle source
# File lib/bali/judge.rb, line 147
def otherly_rule
  @otherly_rule ||= other_rule_group ? other_rule_group.find_rule(term, operation) : nil
end
record_class() click to toggle source
# File lib/bali/judge.rb, line 118
def record_class
  record.is_a?(Class) ? record : record.class
end
reverse_value(value) click to toggle source
# File lib/bali/judge.rb, line 175
def reverse_value(value)
  case value
  when DEFINITE_TRUE then DEFINITE_FALSE
  when DEFINITE_FALSE then DEFINITE_TRUE
  when FUZY_FALSE then FUZY_TRUE
  when FUZY_TRUE then FUZY_FALSE
  end
end
reversed_term() click to toggle source
# File lib/bali/judge.rb, line 164
def reversed_term
  case term
  when :can then :cant
  when :cant then :can
  end
end
rule() click to toggle source
# File lib/bali/judge.rb, line 142
def rule
  # rule group may be nil, for when user checking for undefined rule group
  @rule ||= rule_group ? rule_group.find_rule(term, operation) : nil
end
rule_group() click to toggle source
# File lib/bali/judge.rb, line 130
def rule_group
  @rule_group ||= rule_group_for role
end
rule_group_for(role) click to toggle source
# File lib/bali/judge.rb, line 126
def rule_group_for(role)
  ruler.nil? ? nil : ruler[role]
end
ruler() click to toggle source
# File lib/bali/judge.rb, line 122
def ruler
  @ruler ||= Bali::Ruler.for record_class
end