module Praxis::Mapper::ActiveModelCompat::ClassMethods

Public Instance Methods

_add_includes(base, includes) click to toggle source
# File lib/praxis/mapper/active_model_compat.rb, line 94
def _add_includes(base, includes)
  base.includes(includes) # includes(nil) seems to have no effect
end
_all(conditions = {}) click to toggle source
# File lib/praxis/mapper/active_model_compat.rb, line 90
def _all(conditions = {})
  where(conditions)
end
_field_selector_query_builder_class() click to toggle source
# File lib/praxis/mapper/active_model_compat.rb, line 22
def _field_selector_query_builder_class
  Praxis::Extensions::FieldSelection::ActiveRecordQuerySelector
end
_filter_query_builder_class() click to toggle source
# File lib/praxis/mapper/active_model_compat.rb, line 18
def _filter_query_builder_class
  Praxis::Extensions::AttributeFiltering::ActiveRecordFilterQueryBuilder
end
_first() click to toggle source
# File lib/praxis/mapper/active_model_compat.rb, line 98
def _first
  first
end
_get(condition) click to toggle source

Compatible reader accessors

# File lib/praxis/mapper/active_model_compat.rb, line 86
def _get(condition)
  find_by(condition)
end
_join_foreign_key_for(assoc_reflection) click to toggle source
# File lib/praxis/mapper/active_model_compat.rb, line 69
def _join_foreign_key_for(assoc_reflection)
  if ActiveRecord.gem_version >= Gem::Version.new('6.1')
    assoc_reflection.join_foreign_key.to_sym
  else # below 6.1
    assoc_reflection.join_keys.foreign_key.to_sym
  end
end
_join_primary_key_for(assoc_reflection) click to toggle source
# File lib/praxis/mapper/active_model_compat.rb, line 77
def _join_primary_key_for(assoc_reflection)
  if ActiveRecord.gem_version >= Gem::Version.new('6.1')
    assoc_reflection.join_primary_key.to_sym
  else # below 6.1
    assoc_reflection.join_keys.key.to_sym
  end
end
_last() click to toggle source
# File lib/praxis/mapper/active_model_compat.rb, line 102
def _last
  last
end
_pagination_query_builder_class() click to toggle source
# File lib/praxis/mapper/active_model_compat.rb, line 26
def _pagination_query_builder_class
  Praxis::Extensions::Pagination::ActiveRecordPaginationHandler
end
_praxis_associations() click to toggle source
# File lib/praxis/mapper/active_model_compat.rb, line 30
def _praxis_associations
  # Memoize the hash in the model, to avoid recomputing expensive AR reflection lookups
  # NOTE: should this be finalized with the resources? or do we know if all associations and such that are needed here will never change?
  return @_praxis_associations if @_praxis_associations

  orig = reflections.clone

  @_praxis_associations = orig.each_with_object({}) do |(k, v), hash|
    # Assume an 'id' primary key if the system is initializing without AR connected
    # (or without the tables created). This probably means that it's a rake task initializing or so...
    pkey = \
      if v.klass.connected? && v.klass.table_exists?
        v.klass.primary_key
      else
        'id'
      end
    info = { model: v.klass, primary_key: pkey }
    info[:type] = \
      case v
      when ActiveRecord::Reflection::BelongsToReflection
        :many_to_one
      when ActiveRecord::Reflection::HasManyReflection, ActiveRecord::Reflection::HasOneReflection
        :one_to_many
      when ActiveRecord::Reflection::ThroughReflection
        :many_to_many
      else
        raise "Unknown association type: #{v.class.name} on #{v.klass.name} for #{v.name}"
      end
    # Call out any local (i.e., of this model) columns that participate in the association
    info[:local_key_columns] = local_columns_used_for_the_association(info[:type], v)
    info[:remote_key_columns] = remote_columns_used_for_the_association(info[:type], v)

    if v.is_a?(ActiveRecord::Reflection::ThroughReflection)
      info[:through] = v.through_reflection.name # TODO: is this correct?
    end
    hash[k.to_sym] = info
  end
end

Private Instance Methods

local_columns_used_for_the_association(type, assoc_reflection) click to toggle source
# File lib/praxis/mapper/active_model_compat.rb, line 108
def local_columns_used_for_the_association(type, assoc_reflection)
  case type
  when :one_to_many
    # The associated table  will point to us by key (usually the PK, but not always)
    [_join_foreign_key_for(assoc_reflection)]
  when :many_to_one
    # We have the FKs to the associated model
    [_join_foreign_key_for(assoc_reflection)]
  when :many_to_many
    ref = resolve_closest_through_reflection(assoc_reflection)
    # The associated middle table will point to us by key (usually the PK, but not always)
    [_join_foreign_key_for(ref)] # The foreign key that the last through table points to
  else
    raise "association type #{type} not supported"
  end
end
remote_columns_used_for_the_association(type, assoc_reflection) click to toggle source
# File lib/praxis/mapper/active_model_compat.rb, line 125
def remote_columns_used_for_the_association(type, assoc_reflection)
  # It seems that since the reflection is the target of the association, using the join_keys.key
  # will always get us the right column
  case type
  when :one_to_many, :many_to_one, :many_to_many
    [_join_primary_key_for(assoc_reflection)]
  else
    raise "association type #{type} not supported"
  end
end
resolve_closest_through_reflection(ref) click to toggle source

Keep following the association reflections as long as there are middle ones (i.e., through) until we come to the one next to the source

# File lib/praxis/mapper/active_model_compat.rb, line 138
def resolve_closest_through_reflection(ref)
  return ref unless ref.through_reflection?

  resolve_closest_through_reflection(ref.through_reflection)
end