module CanCanCan::BabySqueel::AttributeMapper

Implements mapping attributes, values, and comparators for a given model to appropriate database equivalents.

This implements:

- comparing values against an array: interpreted as any value for ==, none of the values for !=.
- mapping foreign keys to IDs

Public Instance Methods

comparator_for_array(comparator, value) click to toggle source

Maps the given comparator to the IN/NOT IN operator.

@param [Symbol] comparator The comparator to get the SqueeL comparator for. @param [Array] value The acceptable/rejected values. @return [Array<(Symbol, Array<(Symbol, Object)>)>] The combinator, and an array of comparisons,

each with the comparator to use, and the value to compare against.
# File lib/cancancan/baby_squeel/attribute_mapper.rb, line 86
def comparator_for_array(comparator, value)
  case comparator
  when :eq then [:and, [[:in, value]]]
  when :not_eq then [:and, [[:not_in, value]]]
  end
end
comparator_for_exclusive_range(comparator, value) click to toggle source

Maps the given comparator to a range comparison.

@param [Symbol] comparator The comparator to get the Squeel comparator for. @param [Range] value The acceptable/rejected values. @return [Array<Array<(Symbol, Object)>>] An array of comparisons, each with the comparator

to use, and the value to compare against.
# File lib/cancancan/baby_squeel/attribute_mapper.rb, line 113
def comparator_for_exclusive_range(comparator, value)
  case comparator
  when :eq then [:and, [[:gteq, value.first], [:lt, value.last]]]
  when :not_eq then [:or, [[:lt, value.first], [:gteq, value.last]]]
  end
end
comparator_for_inclusive_range(comparator, value) click to toggle source

Maps the given comparator to a range comparison.

@param [Symbol] comparator The comparator to get the Squeel comparator for. @param [Range] value The acceptable/rejected values. @return [Array<Array<(Symbol, Object)>>] An array of comparisons, each with the comparator

to use, and the value to compare against.
# File lib/cancancan/baby_squeel/attribute_mapper.rb, line 126
def comparator_for_inclusive_range(comparator, value)
  case comparator
  when :eq then [:and, [[:gteq, value.first], [:lteq, value.last]]]
  when :not_eq then [:or, [[:lt, value.first], [:gt, value.last]]]
  end
end
comparator_for_range(comparator, value) click to toggle source

Maps the given comparator to a range comparison.

@param [Symbol] comparator The comparator to get the Squeel comparator for. @param [Range] value The acceptable/rejected values. @return [Array<(Symbol, Array<(Symbol, Object)>)>] The combinator, and an array of comparisons,

each with the comparator to use, and the value to compare against.
# File lib/cancancan/baby_squeel/attribute_mapper.rb, line 99
def comparator_for_range(comparator, value)
  if value.exclude_end?
    comparator_for_exclusive_range(comparator, value)
  else
    comparator_for_inclusive_range(comparator, value)
  end
end
map_association(model_class, key, value) click to toggle source

Picks the table column to compare the value against for the given key.

This sets associations to use the proper foreign key column.

@param [Class] model_class The model class which the key references. @param [Symbol] key The column being compared. @param value The value to be comparing against. @return [Array<(Symbol, Object)>] A tuple containing the column to compare with and the value

to compare with.
# File lib/cancancan/baby_squeel/attribute_mapper.rb, line 53
def map_association(model_class, key, value)
  if (association = model_class.reflect_on_association(key))
    key = association.foreign_key
    value = value.id
  end

  [key, value]
end
squeel_comparator_for(comparator, value) click to toggle source

Maps the given comparator to a comparator appropriate for the given value.

Array values are interpreted as alternative choices allowed or disallowed.

Ranges are interpreted as start/end pairs, respecting the exclusion of the end point.

@param [Symbol] comparator The comparator to get the appropriate Squeel comparator for. @param value The value to be comparing against. @return [Array<Array<(Symbol, Object)>>] An array of comparisons, each with the comparator

to use, and the value to compare against.
# File lib/cancancan/baby_squeel/attribute_mapper.rb, line 72
def squeel_comparator_for(comparator, value)
  case value
  when Array then comparator_for_array(comparator, value)
  when Range then comparator_for_range(comparator, value)
  else [:and, [[comparator, value]]]
  end
end
squeel_comparison_for(model_class, key, comparator, value) click to toggle source

Picks the appropriate column, comparator, and value to use in the Squeel expression.

This checks for association references: this will use the appropriate column name. Array values are interpreted as alternative choices allowed or disallowed. Ranges are converted to appropriate comparator pairs.

The return value is a tuple:

- The first element is a combinator to be used on the comparisons.
- The second element is an array of comparisons: each comparison is a tuple of
  (key, comparator, value)

The appropriate expression is the combination of all the comparisons, using the combinator returned.

@example Attribute Ranges

squeel_comparison_for(User, :id, :eq, 1..5) #=> [:and, [[:id, :gteq, 1], [:id, :lteq, 5]]]

@example Association Objects

squeel_comparison_for(Post, :comment, :eq, comment) #=> [:and, [[:comment_id, :eq, 1]]]

@param [Class] model_class The model class which the key references. @param [Symbol] key The column being compared. @param [Symbol] comparator The comparator to get the appropriate Squeel comparator for. @param value The value to be comparing against. @return [Array<(Symbol, Array<(Symbol, Symbol, Object)>)>] A tuple containing the combinator for

the comparisons, and a sequence of comparisons.
# File lib/cancancan/baby_squeel/attribute_mapper.rb, line 37
def squeel_comparison_for(model_class, key, comparator, value)
  key, value = map_association(model_class, key, value)

  combinator, comparisons = squeel_comparator_for(comparator, value)
  [combinator, comparisons.map { |comp| comp.unshift(key) }]
end