module ActiveRecord::Pull::Alpha::Core

Public Class Methods

pull(record, q) click to toggle source
# File lib/activerecord/pull/alpha/core.rb, line 10
def pull(record, q)
  case q
  when :*, '*'
    pull_all(record)
  when Symbol, String
    pull_symbol(record, q)
  when Hash
    pull_hash(record, q)
  when Array
    q.map { |pat| pull(record, pat) }.reduce(&:merge)
  else
    raise "Invalid pull syntax: #{q.inspect}"
  end
end
pull_many(records, q) click to toggle source
# File lib/activerecord/pull/alpha/core.rb, line 6
def pull_many(records, q)
  records.map { |r| pull(r, q) }
end

Private Class Methods

pull_all(record) click to toggle source

TODO: this should pull all associations

# File lib/activerecord/pull/alpha/core.rb, line 77
def pull_all(record)
  names  = record.class.attribute_names
  nested = record.class.nested_attributes_options
  attrs  = pull(record, names)
        
  if nested.empty?
    attrs
  else
    nested.keys.reduce(attrs) do |h, assoc|
      assoc_val = record.send(assoc)
      if assoc_val.nil? || assoc_val.is_a?(Enumerable) && assoc_val.empty?
        h
      elsif assoc_val.is_a?(Enumerable)
        h.merge!(assoc => assoc_val.map { |rec| pull_all(rec) }.reject(&:nil?))
      else
        h.merge!(assoc => pull_all(assoc_val))
      end
    end
  end
end
pull_hash(record, hash) click to toggle source
# File lib/activerecord/pull/alpha/core.rb, line 61
def pull_hash(record, hash)
  hash.reduce({}) do |h, (attr, pat)|
    val = resolved_value(record, attr)
    if val.nil?
      h
    elsif ref_type?(val) && val.is_a?(Enumerable)
      h.merge!(attr => val.map { |v| pull(v, pat) })
    elsif ref_type?(val)
      h.merge!(attr => pull(val, pat))
    else
      h.merge!(attr => val)
    end
  end
end
pull_symbol(record, attr) click to toggle source
# File lib/activerecord/pull/alpha/core.rb, line 50
def pull_symbol(record, attr)
  val = resolved_value(record, attr)
  if ref_type?(val) && val.is_a?(Enumerable)
    { attr => val.map { |v| pull_all(v) } }
  elsif ref_type?(val)
    { attr => pull_all(val) }
  else
    { attr => val }
  end
end
ref_type?(value) click to toggle source
# File lib/activerecord/pull/alpha/core.rb, line 46
def ref_type?(value)
  value.is_a?(ActiveRecord::Relation) || value.is_a?(ActiveRecord::Base)
end
resolved_value(record, attr) click to toggle source
# File lib/activerecord/pull/alpha/core.rb, line 27
def resolved_value(record, attr)
  if !(val = record[attr]).nil?
    val
  elsif val.nil? and !(reflection = record.class.reflect_on_association(attr)).nil?
    model = reflection.class_name.constantize
    p model
    case reflection
    when ActiveRecord::Reflection::HasManyReflection, ActiveRecord::Reflection::HasAndBelongsToManyReflection
      model.where(reflection.foreign_key => record[record.class.primary_key])
    when ActiveRecord::Reflection::BelongsToReflection
      model.find_by(model.primary_key => record[reflection.foreign_key])
    else
      raise "Don't know how to resolve value for reflection: #{reflection.inspect}"
    end
  else
    nil
  end
end