Module: CanCan

Defined in:
lib/cancan/model_adapters/sti_normalizer.rb,
lib/cancan/rule.rb,
lib/cancan/config.rb,
lib/cancan/ability.rb,
lib/cancan/version.rb,
lib/cancan/relevant.rb,
lib/cancan/exceptions.rb,
lib/cancan/ability/rules.rb,
lib/cancan/ability/actions.rb,
lib/cancan/model_additions.rb,
lib/cancan/rules_compressor.rb,
lib/cancan/conditions_matcher.rb,
lib/cancan/controller_resource.rb,
lib/cancan/controller_additions.rb,
lib/cancan/parameter_validators.rb,
lib/cancan/controller_resource_finder.rb,
lib/cancan/controller_resource_loader.rb,
lib/cancan/controller_resource_builder.rb,
lib/cancan/controller_resource_sanitizer.rb,
lib/cancan/unauthorized_message_resolver.rb,
lib/cancan/model_adapters/default_adapter.rb,
lib/cancan/model_adapters/strategies/base.rb,
lib/cancan/controller_resource_name_finder.rb,
lib/cancan/model_adapters/abstract_adapter.rb,
lib/cancan/ability/strong_parameter_support.rb,
lib/cancan/model_adapters/strategies/subquery.rb,
lib/cancan/model_adapters/conditions_extractor.rb,
lib/cancan/model_adapters/strategies/left_join.rb,
lib/cancan/model_adapters/active_record_adapter.rb,
lib/cancan/model_adapters/conditions_normalizer.rb,
lib/cancan/model_adapters/active_record_4_adapter.rb,
lib/cancan/model_adapters/active_record_5_adapter.rb,
lib/cancan/model_adapters/strategies/joined_alias_exists_subquery.rb,
lib/cancan/model_adapters/strategies/joined_alias_each_rule_as_exists_subquery.rb

Overview

this class is responsible of normalizing the hash of conditions by exploding has_many through associations when a condition is defined with an has_many through association this is exploded in all its parts TODO: it could identify STI and normalize it

Defined Under Namespace

Modules: Ability, ConditionsMatcher, ControllerAdditions, ControllerResourceBuilder, ControllerResourceFinder, ControllerResourceLoader, ControllerResourceNameFinder, ControllerResourceSanitizer, ModelAdapters, ModelAdditions, ParameterValidators, Relevant, UnauthorizedMessageResolver Classes: AccessDenied, AttributeArgumentError, AuthorizationNotPerformed, BlockAndConditionsError, ControllerResource, Error, ImplementationRemoved, NotImplemented, Rule, RulesCompressor, WrongAssociationName

Constant Summary collapse

VERSION =
'3.4.0'.freeze

Class Method Summary collapse

Class Method Details

.accessible_by_strategyObject

Determines how CanCan should build queries when calling accessible_by, if the query will contain a join. The default strategy is `:subquery`.

# config/initializers/cancan.rb
CanCan.accessible_by_strategy = :subquery

Valid strategies are:

  • :subquery - Creates a nested query with all joins, wrapped by a

    WHERE IN query.
    
  • :left_join - Calls the joins directly using `left_joins`, and

    ensures records are unique using `distinct`. Note that
    `distinct` is not reliable in some cases. See
    https://github.com/CanCanCommunity/cancancan/pull/605
    

27
28
29
30
31
# File 'lib/cancan/config.rb', line 27

def self.accessible_by_strategy
  return @accessible_by_strategy if @accessible_by_strategy

  @accessible_by_strategy = default_accessible_by_strategy
end

.accessible_by_strategy=(value) ⇒ Object


44
45
46
47
48
49
50
51
52
# File 'lib/cancan/config.rb', line 44

def self.accessible_by_strategy=(value)
  validate_accessible_by_strategy!(value)

  if value == :subquery && does_not_support_subquery_strategy?
    raise ArgumentError, 'accessible_by_strategy = :subquery requires ActiveRecord 5 or newer'
  end

  @accessible_by_strategy = value
end

.default_accessible_by_strategyObject


33
34
35
36
37
38
39
40
41
42
# File 'lib/cancan/config.rb', line 33

def self.default_accessible_by_strategy
  if does_not_support_subquery_strategy?
    # see https://github.com/CanCanCommunity/cancancan/pull/655 for where this was added
    # the `subquery` strategy (from https://github.com/CanCanCommunity/cancancan/pull/619
    # only works in Rails 5 and higher
    :left_join
  else
    :subquery
  end
end

.does_not_support_subquery_strategy?Boolean

Returns:

  • (Boolean)

74
75
76
77
# File 'lib/cancan/config.rb', line 74

def self.does_not_support_subquery_strategy?
  !defined?(CanCan::ModelAdapters::ActiveRecordAdapter) ||
    CanCan::ModelAdapters::ActiveRecordAdapter.version_lower?('5.0.0')
end

.valid_accessible_by_strategiesObject


4
5
6
7
8
9
10
11
12
# File 'lib/cancan/config.rb', line 4

def self.valid_accessible_by_strategies
  strategies = [:left_join]

  unless does_not_support_subquery_strategy?
    strategies.push(:joined_alias_exists_subquery, :joined_alias_each_rule_as_exists_subquery, :subquery)
  end

  strategies
end

.validate_accessible_by_strategy!(value) ⇒ Object

Raises:

  • (ArgumentError)

68
69
70
71
72
# File 'lib/cancan/config.rb', line 68

def self.validate_accessible_by_strategy!(value)
  return if valid_accessible_by_strategies.include?(value)

  raise ArgumentError, "accessible_by_strategy must be one of #{valid_accessible_by_strategies.join(', ')}"
end

.with_accessible_by_strategy(value) ⇒ Object


54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/cancan/config.rb', line 54

def self.with_accessible_by_strategy(value)
  return yield if value == accessible_by_strategy

  validate_accessible_by_strategy!(value)

  begin
    strategy_was = accessible_by_strategy
    @accessible_by_strategy = value
    yield
  ensure
    @accessible_by_strategy = strategy_was
  end
end