module Subroutine::AssociationFields

Public Instance Methods

clear_field_with_association(field_name) click to toggle source
# File lib/subroutine/association_fields.rb, line 150
def clear_field_with_association(field_name)
  config = get_field_config(field_name)

  if config&.behavior == :association
    clear_field(config.foreign_type_method) if config.polymorphic?
    clear_field(config.foreign_key_method)
    association_cache.delete(config.field_name)
  else
    clear_field_without_association(field_name)
  end
end
fetch_association_instance(_type, _fk, _unscoped = false) click to toggle source
# File lib/subroutine/association_fields.rb, line 178
def fetch_association_instance(_type, _fk, _unscoped = false)
  return nil unless _type && _fk

  klass = _type
  klass = klass.classify.constantize if klass.is_a?(String)

  return nil unless klass

  scope = klass.all
  scope = scope.unscoped if _unscoped

  scope.find(_fk)
end
field_provided_with_association?(field_name) click to toggle source
# File lib/subroutine/association_fields.rb, line 162
def field_provided_with_association?(field_name)
  config = get_field_config(field_name)

  if config&.behavior == :association
    provided = true
    provided &&= field_provided?(config.foreign_type_method) if config.polymorphic?
    provided &&= field_provided?(config.foreign_key_method)
    provided
  elsif config&.behavior == :association_component
    field_provided_without_association?(field_name) ||
      field_provided_without_association?(config.association_name)
  else
    field_provided_without_association?(field_name)
  end
end
get_field_with_association(field_name) click to toggle source
# File lib/subroutine/association_fields.rb, line 133
def get_field_with_association(field_name)
  config = get_field_config(field_name)

  if config&.behavior == :association
    stored_result = association_cache[config.field_name]
    return stored_result unless stored_result.nil?

    fk = config.field_reader? ? send(config.foreign_key_method) : get_field(config.foreign_id_method)
    type = config.field_reader? || !config.polymorphic? ? send(config.foreign_type_method) : get_field(config.foreign_type_method)

    result = fetch_association_instance(type, fk, config.unscoped?)
    association_cache[config.field_name] = result
  else
    get_field_without_association(field_name)
  end
end
maybe_raise_on_association_type_mismatch!(config, record) click to toggle source
# File lib/subroutine/association_fields.rb, line 192
def maybe_raise_on_association_type_mismatch!(config, record)
  return if config.polymorphic?
  return if record.nil?

  klass = config.inferred_class_name.constantize

  return if record.class <= klass || record.class >= klass

  message = "#{klass}(##{klass.object_id}) expected, got #{record.class}(##{record.class.object_id})"

  errors.add(:base, message)
  raise Subroutine::AssociationFields::AssociationTypeMismatchError, self
end
params_with_associations() click to toggle source
# File lib/subroutine/association_fields.rb, line 97
def params_with_associations
  association_fields = field_configurations.select { |_name, config| config.behavior == :association }
  return params if association_fields.empty?

  excepts = []
  association_fields.each_pair do |_name, config|
    excepts |= config.related_field_names
  end

  out = params.except(*excepts)
  association_fields.each_pair do |field_name, config|
    next unless field_provided?(field_name)

    out[field_name] = config.field_reader? ? send(field_name) : get_field(field_name)
  end

  out
end
set_field_with_association(field_name, value, opts = {}) click to toggle source
# File lib/subroutine/association_fields.rb, line 116
def set_field_with_association(field_name, value, opts = {})
  config = get_field_config(field_name)

  if config&.behavior == :association
    maybe_raise_on_association_type_mismatch!(config, value)
    set_field(config.foreign_type_method, value&.class&.name, opts) if config.polymorphic?
    set_field(config.foreign_key_method, value&.id, opts)
    association_cache[config.field_name] = value
  else
    if config&.behavior == :association_component
      clear_field_without_association(config.association_name)
    end

    set_field_without_association(field_name, value, opts)
  end
end
setup_fields_with_association(*args) click to toggle source
# File lib/subroutine/association_fields.rb, line 92
def setup_fields_with_association(*args)
  @association_cache = {}
  setup_fields_without_association(*args)
end