module RiceCooker::Helpers

Public Instance Methods

apply_filter_to_collection(collection, filtering_params, additional = {}) click to toggle source
# File lib/rice_cooker/base/helpers.rb, line 185
def apply_filter_to_collection(collection, filtering_params, additional = {})
  return collection if collection.nil?

  filtering_params.each do |field, value|
    puts "Filtering param #{field} -> #{value}"
    if additional.key?(field) && additional[field].key?(:proc)

      # Si on a fourni des valeurs, on verifie qu'elle matchent
      if additional[field].key?(:all) && additional[field][:all].try(:any?)
        allowed = additional[field][:all].map(&:to_s)
        raise InvalidFilterValueException, "Value #{(value - allowed).to_sentence} is not allowed for filter #{field}, can be #{allowed.to_sentence}" if (value - allowed).any?
      end

      collection = collection.instance_exec(value, &(additional[field][:proc]))
    elsif field =~ /_at$/ && (value.is_a?(String) || value.is_a?(Array))
      collection = collection.where("DATE(#{field}) = ?", [*value])
    elsif value.is_a?(String) || value.is_a?(Array)
      collection = collection.where(field => value)
    elsif value.is_a?(Hash) && value.key?(:proc)
      collection
    end
  end
  collection
end
apply_range_to_collection(collection, ranged_params, additional = {}) click to toggle source
# File lib/rice_cooker/base/helpers.rb, line 354
def apply_range_to_collection(collection, ranged_params, additional = {})
  return collection if collection.nil?

  ranged_params.each do |field, value|
    if additional.key?(field) && additional[field].key?(:proc)

      # Si on a fourni des valeurs, on verifie qu'elle matchent
      if additional[field].key?(:all) && additional[field][:all].try(:any?)
        allowed = additional[field][:all].map(&:to_s)
        raise InvalidRangeValueException, "
          Value #{(value - allowed).to_sentence} is not allowed for range #{field}, can be #{allowed.to_sentence}
        " if (value - allowed).any?
      end
      collection = collection.instance_exec(value.try(:first), value.try(:last), &(additional[field][:proc]))
    elsif value.is_a? Array
      from, to = value.slice(0, 2)
      begin
        collection = collection.where(field => from..to)
      rescue ArgumentError
        raise InvalidRangeValueException, "
          Unable to create a range between values '#{from}' and '#{to}'
        "
      end
    elsif value.is_a?(Hash) && value.key?(:proc)
      collection
    end
  end
  collection
end
apply_search_to_collection(col, searching_params, additional = {}) click to toggle source
# File lib/rice_cooker/base/helpers.rb, line 308
def apply_search_to_collection(col, searching_params, additional = {})
  return col if col.nil?

  searching_params.each do |field, value|
    if additional.key?(field) && additional[field].key?(:proc)
      col = col.instance_exec(value, &(additional[field][:proc]))
    elsif value.is_a?(String)
      col = (col.where(col.model.arel_table[field.to_sym].matches("%#{value.join(' ')}%")) rescue col)
    elsif value.is_a?(Array)
      col = reduce_where(col, field, value)
    elsif value.is_a?(Hash) && value.key?(:proc)
      col
    end
  end
  col
end
apply_sort_to_collection(collection, sorting_params) click to toggle source
# File lib/rice_cooker/base/helpers.rb, line 110
def apply_sort_to_collection(collection, sorting_params)
  return collection unless collection.any?
  # p "Before apply: #{sorting_params.inspect}"
  collection.order(sorting_params)
end
check_filtering_param(filtering_param, allowed) click to toggle source

Our little barrier <3

# File lib/rice_cooker/base/helpers.rb, line 138
def check_filtering_param(filtering_param, allowed)
  πŸ”ž = filtering_param.keys.map(&:to_sym) - allowed.map(&:to_sym)
  raise InvalidFilterException, "Attributes #{πŸ”ž.map(&:to_s).to_sentence} doesn't exists or aren't filterables. Available filters are: #{allowed.to_sentence}" if πŸ”ž.any?
end
check_ranged_param(ranged_param, allowed) click to toggle source

Our little barrier <3

# File lib/rice_cooker/base/helpers.rb, line 349
def check_ranged_param(ranged_param, allowed)
  πŸ”ž = ranged_param.keys.map(&:to_sym) - allowed.map(&:to_sym)
  raise InvalidRangeException, "Attributes #{πŸ”ž.map(&:to_s).to_sentence} doesn't exists or aren't rangeables. Available ranges are: #{allowed.to_sentence}" if πŸ”ž.any?
end
check_searching_param(searching_param, allowed) click to toggle source

Our little barrier <3

# File lib/rice_cooker/base/helpers.rb, line 233
def check_searching_param(searching_param, allowed)
  πŸ”ž = searching_param.keys.map(&:to_sym) - allowed.map(&:to_sym)
  raise InvalidSearchException, "Attributes #{πŸ”ž.map(&:to_s).to_sentence} doesn't exists or aren't searchables. Available searchs are: #{allowed.to_sentence}" if πŸ”ž.any?
end
check_sorting_param(model, sorting_param) click to toggle source
# File lib/rice_cooker/base/helpers.rb, line 97
def check_sorting_param(model, sorting_param)
  sort_field = sorting_param[:field]
  sortable_fields = sortable_fields_for(model)

  unless sortable_fields.include? sort_field.to_sym
    raise InvalidSortException, "The #{sort_field} field is not sortable"
  end
end
filterable_fields_for(model) click to toggle source

Overridable method for available filterable fields

# File lib/rice_cooker/base/helpers.rb, line 41
def filterable_fields_for(model)
  if model.respond_to?(:filterable_fields)
    model.filterable_fields.map(&:to_sym)
  elsif model.respond_to?(:column_names)
    model.column_names.map(&:to_sym)
  else
    []
  end
end
format_additional_param(additional, context_format = 'filtering') click to toggle source

On va essayer de garder un format commun, qui est:

β€œ` filter: {

proc: -> (values) { * je fais des trucs avec les values * },
all: ['les', 'valeurs', 'aceptΓ©es'],
description: "La description dans la doc"

} β€œ`

On va donc transformer `additional` dans le format ci-dessus

# File lib/rice_cooker/base/helpers.rb, line 155
def format_additional_param(additional, context_format = 'filtering')
  if additional.is_a? Hash
    additional = additional.map do |field, value|
      if value.is_a?(Hash)
        value = {
          proc: nil,
          all: [],
          description: ''
        }.merge(value)
      elsif value.is_a? Array
        value = {
          proc: value.try(:at, 0),
          all: value.try(:at, 1) || [],
          description: value.try(:at, 2) || ''
        }
      elsif value.is_a? Proc
        value = {
          proc: value,
          all: [],
          description: ''
        }
      else
        raise "Unable to format addional #{context_format} params (got #{additional})"
      end
      [field, value]
    end.to_h
  end
  additional
end
fuzzy_fields_for(model) click to toggle source

Overridable method for available fuzzy fields

# File lib/rice_cooker/base/helpers.rb, line 61
def fuzzy_fields_for(model)
  if model.respond_to?(:fuzzy_fields)
    model.fuzzy_fields.map(&:to_sym)
  else
    searchable_fields_for(model)
  end
end
param_from_defaults(sorting_params) click to toggle source
# File lib/rice_cooker/base/helpers.rb, line 106
def param_from_defaults(sorting_params)
  sorting_params.map { |k, v| "#{v == :desc ? '-' : ''}#{k}" }.join(',')
end
parse_filtering_param(filtering_param, allowed_params) click to toggle source

Va transformer le param url en hash exploitable

# File lib/rice_cooker/base/helpers.rb, line 119
def parse_filtering_param(filtering_param, allowed_params)
  return {} unless filtering_param.present?

  fields = {}

  # Extract the fields for each type from the fields parameters
  if filtering_param.is_a?(Hash)
    filtering_param.each do |field, value|
      resource_fields = value.split(',') unless value.nil? || value.empty?
      fields[field.to_sym] = resource_fields
    end
  else
    raise InvalidFilterException, "Invalid filter format for #{filtering_param}"
  end
  check_filtering_param(fields, allowed_params)
  fields
end
parse_ranged_param(ranged_param, allowed_params) click to toggle source

Va transformer le param url en hash exploitable

# File lib/rice_cooker/base/helpers.rb, line 328
def parse_ranged_param(ranged_param, allowed_params)
  return {} unless ranged_param.present?

  fields = {}

  # Extract the fields for each type from the fields parameters
  if ranged_param.is_a?(Hash)
    ranged_param.each do |field, value|
      resource_fields = value.split(',') unless value.nil? || value.empty?
      raise InvalidRangeException, "Invalid range format for #{ranged_param}. Too many arguments for filter (#{resource_fields})." if resource_fields.length > 2
      raise InvalidRangeException, "Invalid range format for #{ranged_param}. Begin and end must be separated by a comma (,)." if resource_fields.length < 2
      fields[field.to_sym] = resource_fields
    end
  else
    raise InvalidRangeException, "Invalid range format for #{ranged_param}"
  end
  check_ranged_param(fields, allowed_params)
  fields
end
parse_searching_param(searching_param, allowed_params) click to toggle source

Va transformer le param url en hash exploitable

# File lib/rice_cooker/base/helpers.rb, line 214
def parse_searching_param(searching_param, allowed_params)
  return {} unless searching_param.present?

  fields = {}

  # Extract the fields for each type from the fields parameters
  if searching_param.is_a?(Hash)
    searching_param.each do |field, value|
      resource_fields = value.split(',') unless value.nil? || value.empty?
      fields[field.to_sym] = resource_fields
    end
  else
    raise InvalidSearchException, "Invalid search format for #{searching_param}"
  end
  check_searching_param(fields, allowed_params)
  fields
end
parse_sorting_param(sorting_param, model) click to toggle source

model -> resource_class with inherited resources

# File lib/rice_cooker/base/helpers.rb, line 81
def parse_sorting_param(sorting_param, model)
  return {} unless sorting_param.present?

  sorting_params = CSV.parse_line(URI.unescape(sorting_param)).collect do |sort|
    sorting_param = if sort.start_with?('-')
                      { field: sort[1..-1].to_s.to_sym, direction: :desc }
                    else
                      { field: sort.to_s.to_sym, direction: :asc }
                    end

    check_sorting_param(model, sorting_param)
    sorting_param
  end
  sorting_params.map { |par| [par[:field], par[:direction]] }.to_h
end
rangeable_fields_for(model) click to toggle source

Overridable method for available rangeable fields

# File lib/rice_cooker/base/helpers.rb, line 70
def rangeable_fields_for(model)
  if model.respond_to?(:rangeable_fields)
    model.rangeable_fields.map(&:to_sym)
  else
    filterable_fields_for(model)
  end
end
reduce_fields_where(col, fields, value) click to toggle source
# File lib/rice_cooker/base/helpers.rb, line 289
def reduce_fields_where(col, fields, value)
  reducer = nil
  fields.each do |f|
    case col.model.columns.select{|e| e.name.to_sym == f.to_sym}.first.type
    when :string
      query = col.model.arel_table[f.to_sym].matches("%#{value.to_s}%")
    when :integer
      query = col.model.arel_table[f.to_sym].eq(value.to_i)
    # when :boolean
    #   query = col.model.where(false)
    else
      query = false
    end

    reducer = (reducer ? reducer.or(query) : query) if query
  end
  col.where(reducer)
end
reduce_where(col, field, value) click to toggle source
# File lib/rice_cooker/base/helpers.rb, line 280
def reduce_where(col, field, value)
  reducer = nil
  value.each do |v|
    query = col.model.arel_table[field.to_sym].matches("%#{v.to_s}%")
    reducer = (reducer ? reducer.or(query) : query)
  end
  col.where(reducer)
end
searchable_fields_for(model) click to toggle source

Overridable method for available searchable fields

# File lib/rice_cooker/base/helpers.rb, line 52
def searchable_fields_for(model)
  if model.respond_to?(:searchable_fields)
    model.searchable_fields.map(&:to_sym)
  else
    filterable_fields_for(model)
  end
end
sortable_fields_for(model) click to toggle source

Overridable method for available sortable fields

# File lib/rice_cooker/base/helpers.rb, line 30
def sortable_fields_for(model)
  if model.respond_to?(:sortable_fields)
    model.sortable_fields.map(&:to_sym)
  elsif model.respond_to?(:column_names)
    model.column_names.map(&:to_sym)
  else
    []
  end
end