Class: CanCan::ModelAdapters::Strategies::JoinedAliasEachRuleAsExistsSubquery

Inherits:
Base
  • Object
show all
Defined in:
lib/cancan/model_adapters/strategies/joined_alias_each_rule_as_exists_subquery.rb

Instance Attribute Summary

Attributes inherited from Base

#adapter, #relation, #where_conditions

Instance Method Summary collapse

Methods inherited from Base

#aliased_table_name, #initialize, #quoted_aliased_table_name, #quoted_table_name

Constructor Details

This class inherits a constructor from CanCan::ModelAdapters::Strategies::Base

Instance Method Details

#current_path_to_hash(current_path) ⇒ Object

Converts an array like [:child, :grand_child] into a hash like {grand_child: {}



78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/cancan/model_adapters/strategies/joined_alias_each_rule_as_exists_subquery.rb', line 78

def current_path_to_hash(current_path)
  hash_joins = {}
  current_hash_joins = hash_joins

  current_path.each do |path_part|
    new_hash = {}
    current_hash_joins[path_part] = new_hash
    current_hash_joins = new_hash
  end

  hash_joins
end

#double_exists_sqlObject



16
17
18
19
20
21
22
23
24
25
# File 'lib/cancan/model_adapters/strategies/joined_alias_each_rule_as_exists_subquery.rb', line 16

def double_exists_sql
  double_exists_sql = ''

  compressed_rules.each_with_index do |rule, index|
    double_exists_sql << ' OR ' if index.positive?
    double_exists_sql << "EXISTS (#{sub_query_for_rule(rule).to_sql})"
  end

  double_exists_sql
end

#execute!Object



7
8
9
10
11
12
13
14
# File 'lib/cancan/model_adapters/strategies/joined_alias_each_rule_as_exists_subquery.rb', line 7

def execute!
  model_class
    .joins(
      "JOIN #{quoted_table_name} AS #{quoted_aliased_table_name} ON " \
      "#{quoted_aliased_table_name}.#{quoted_primary_key} = #{quoted_table_name}.#{quoted_primary_key}"
    )
    .where(double_exists_sql)
end

#extra_joins_recursive(current_path, conditions, joins, left_joins) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
# File 'lib/cancan/model_adapters/strategies/joined_alias_each_rule_as_exists_subquery.rb', line 55

def extra_joins_recursive(current_path, conditions, joins, left_joins)
  conditions.each do |key, value|
    if value.is_a?(Hash)
      current_path << key
      extra_joins_recursive(current_path, value, joins, left_joins)
      current_path.pop
    else
      extra_joins_recursive_merge_joins(current_path, value, joins, left_joins)
    end
  end
end

#extra_joins_recursive_merge_joins(current_path, value, joins, left_joins) ⇒ Object



67
68
69
70
71
72
73
74
75
# File 'lib/cancan/model_adapters/strategies/joined_alias_each_rule_as_exists_subquery.rb', line 67

def extra_joins_recursive_merge_joins(current_path, value, joins, left_joins)
  hash_joins = current_path_to_hash(current_path)

  if value.nil?
    left_joins.deep_merge!(hash_joins)
  else
    joins.deep_merge!(hash_joins)
  end
end

#extract_joins_from_rule(rule) ⇒ Object



47
48
49
50
51
52
53
# File 'lib/cancan/model_adapters/strategies/joined_alias_each_rule_as_exists_subquery.rb', line 47

def extract_joins_from_rule(rule)
  joins = {}
  left_joins = {}

  extra_joins_recursive([], rule.conditions, joins, left_joins)
  [joins, left_joins]
end

#sub_query_for_rule(rule) ⇒ Object



27
28
29
30
31
32
# File 'lib/cancan/model_adapters/strategies/joined_alias_each_rule_as_exists_subquery.rb', line 27

def sub_query_for_rule(rule)
  conditions_extractor = ConditionsExtractor.new(model_class)
  rule_where_conditions = extract_multiple_conditions(conditions_extractor, [rule])
  joins_hash, left_joins_hash = extract_joins_from_rule(rule)
  sub_query_for_rules_and_join_hashes(rule_where_conditions, joins_hash, left_joins_hash)
end

#sub_query_for_rules_and_join_hashes(rule_where_conditions, joins_hash, left_joins_hash) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/cancan/model_adapters/strategies/joined_alias_each_rule_as_exists_subquery.rb', line 34

def sub_query_for_rules_and_join_hashes(rule_where_conditions, joins_hash, left_joins_hash)
  model_class
    .select('1')
    .joins(joins_hash)
    .left_joins(left_joins_hash)
    .where(
      "#{quoted_table_name}.#{quoted_primary_key} = " \
      "#{quoted_aliased_table_name}.#{quoted_primary_key}"
    )
    .where(rule_where_conditions)
    .limit(1)
end