class ActiveHash::Relation

Attributes

all_records[RW]
conditions[RW]
klass[RW]
order_values[RW]

Public Class Methods

new(klass, all_records, conditions = nil, order_values = nil) click to toggle source
# File lib/active_hash/relation.rb, line 12
def initialize(klass, all_records, conditions = nil, order_values = nil)
  self.klass = klass
  self.all_records = all_records
  self.conditions = Conditions.wrap(conditions || [])
  self.order_values = order_values || []
end

Public Instance Methods

all(options = {}) click to toggle source
# File lib/active_hash/relation.rb, line 95
def all(options = {})
  if options.key?(:conditions)
    where(options[:conditions])
  else
    where({})
  end
end
count() click to toggle source
# File lib/active_hash/relation.rb, line 137
def count
  length
end
find(id = nil, *args, &block) click to toggle source
# File lib/active_hash/relation.rb, line 111
def find(id = nil, *args, &block)
  case id
    when :all
      all
    when :first
      all(*args).first
    when Array
      id.map { |i| find(i) }
    when nil
      raise RecordNotFound.new("Couldn't find #{klass.name} without an ID", klass.name, "id") unless block_given?
      records.find(&block) # delegate to Enumerable#find if a block is given
    else
      find_by_id(id) || begin
        raise RecordNotFound.new("Couldn't find #{klass.name} with ID=#{id}", klass.name, "id", id)
      end
  end
end
find_by(options) click to toggle source
# File lib/active_hash/relation.rb, line 103
def find_by(options)
  where(options).first
end
find_by!(options) click to toggle source
# File lib/active_hash/relation.rb, line 107
def find_by!(options)
  find_by(options) || (raise RecordNotFound.new("Couldn't find #{klass.name}", klass.name))
end
find_by_id(id) click to toggle source
# File lib/active_hash/relation.rb, line 129
def find_by_id(id)
  index = klass.send(:record_index)[id.to_s] # TODO: Make index in Base publicly readable instead of using send?
  return unless index

  record = all_records[index]
  record if conditions.matches?(record)
end
ids() click to toggle source
# File lib/active_hash/relation.rb, line 154
def ids
  pluck(:id)
end
invert_where() click to toggle source
# File lib/active_hash/relation.rb, line 55
def invert_where
  spawn.invert_where!
end
invert_where!() click to toggle source
# File lib/active_hash/relation.rb, line 59
def invert_where!
  conditions.map(&:invert!)
  self
end
method_missing(method_name, *args) click to toggle source
Calls superclass method
# File lib/active_hash/relation.rb, line 166
def method_missing(method_name, *args)
  return super unless klass.scopes&.key?(method_name)

  instance_exec(*args, &klass.scopes[method_name])
end
order(*options) click to toggle source
# File lib/active_hash/relation.rb, line 42
def order(*options)
  spawn.order!(*options)
end
order!(*options) click to toggle source
# File lib/active_hash/relation.rb, line 68
def order!(*options)
  check_if_method_has_arguments!(:order, options)
  self.order_values += preprocess_order_args(options)
  self
end
pick(*column_names) click to toggle source
# File lib/active_hash/relation.rb, line 158
def pick(*column_names)
  pluck(*column_names).first
end
pluck(*column_names) click to toggle source
# File lib/active_hash/relation.rb, line 145
def pluck(*column_names)
  if column_names.length == 1
    column_name = column_names.first
    all.map { |record| record.public_send(column_name) }
  else
    all.map { |record| column_names.map { |column_name| record.public_send(column_name) } }
  end
end
pretty_print(pp) click to toggle source
# File lib/active_hash/relation.rb, line 25
def pretty_print(pp)
  pp.pp(entries.to_ary)
end
records() click to toggle source
# File lib/active_hash/relation.rb, line 83
def records
  @records ||= begin
    filtered_records = apply_conditions(all_records, conditions)
    ordered_records = apply_order_values(filtered_records, order_values) # rubocop:disable Lint/UselessAssignment
  end
end
reload() click to toggle source
# File lib/active_hash/relation.rb, line 90
def reload
  @records = nil # Reset records
  self
end
reorder(*options) click to toggle source
# File lib/active_hash/relation.rb, line 46
def reorder(*options)
  spawn.reorder!(*options)
end
reorder!(*options) click to toggle source
# File lib/active_hash/relation.rb, line 74
def reorder!(*options)
  check_if_method_has_arguments!(:order, options)

  self.order_values = preprocess_order_args(options)
  @records = apply_order_values(records, order_values)

  self
end
respond_to_missing?(method_name, include_private = false) click to toggle source
Calls superclass method
# File lib/active_hash/relation.rb, line 172
def respond_to_missing?(method_name, include_private = false)
  klass.scopes&.key?(method_name) || super
end
size() click to toggle source
# File lib/active_hash/relation.rb, line 141
def size
  length
end
spawn() click to toggle source
# File lib/active_hash/relation.rb, line 64
def spawn
  self.class.new(klass, all_records, conditions, order_values)
end
to_ary() click to toggle source
# File lib/active_hash/relation.rb, line 162
def to_ary
  records.dup
end
where(conditions_hash = :chain) click to toggle source
# File lib/active_hash/relation.rb, line 19
def where(conditions_hash = :chain)
  return WhereChain.new(self) if conditions_hash == :chain

  spawn.where!(conditions_hash)
end
where!(conditions_hash, inverted = false) click to toggle source
# File lib/active_hash/relation.rb, line 50
def where!(conditions_hash, inverted = false)
  self.conditions << Condition.new(conditions_hash)
  self
end

Private Instance Methods

apply_conditions(records, conditions) click to toggle source
# File lib/active_hash/relation.rb, line 180
def apply_conditions(records, conditions)
  return records if conditions.blank?

  records.select do |record|
    conditions.matches?(record)
  end
end
apply_order_values(records, args) click to toggle source
# File lib/active_hash/relation.rb, line 203
def apply_order_values(records, args)
  ordered_records = records.dup

  args.each do |arg|
    field, dir = if arg.is_a?(Hash)
                   arg.to_a.flatten.map(&:to_sym)
                 elsif arg.is_a?(Array)
                   arg.map(&:to_sym)
                 else
                   arg.to_sym
                 end

    ordered_records.sort! do |a, b|
      if dir.present? && dir.to_sym.upcase.equal?(:DESC)
        b[field] <=> a[field]
      else
        a[field] <=> b[field]
      end
    end
  end

  ordered_records
end
check_if_method_has_arguments!(method_name, args) click to toggle source
# File lib/active_hash/relation.rb, line 188
def check_if_method_has_arguments!(method_name, args)
  return unless args.blank?

  raise ArgumentError,
        "The method .#{method_name}() must contain arguments."
end
preprocess_order_args(order_args) click to toggle source
# File lib/active_hash/relation.rb, line 195
def preprocess_order_args(order_args)
  order_args.reject!(&:blank?)
  return order_args.reverse! unless order_args.first.is_a?(String)

  ary = order_args.first.split(', ')
  ary.map! { |e| e.split(/\W+/) }.reverse!
end