Class: Babik::Association::ForeignAssociationChain

Inherits:
Object
  • Object
show all
Defined in:
lib/babik/queryset/lib/association/foreign_association_chain.rb

Overview

Association chain for association paths An association chain is a chain of associations where the target model of association i is the origin model of association i + 1 Remember, an association path is of the form: zone::parent_zone, category::posts::tags

Direct Known Subclasses

SelectRelatedAssociationChain

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, association_path, selection_path) ⇒ ForeignAssociationChain

Construct the association chain

Parameters:

  • model (ActiveRecord::Base)

    origin model

  • association_path (Array)

    association path as an array.

  • selection_path (String, Symbol)

    selection path used only to raise errors.



18
19
20
21
22
23
# File 'lib/babik/queryset/lib/association/foreign_association_chain.rb', line 18

def initialize(model, association_path, selection_path)
  @model = model
  @association_path = association_path
  @selection_path = selection_path
  _init_associations
end

Instance Attribute Details

#associationsObject (readonly)

Returns the value of attribute associations.



12
13
14
# File 'lib/babik/queryset/lib/association/foreign_association_chain.rb', line 12

def associations
  @associations
end

#modelObject (readonly)

Returns the value of attribute model.



12
13
14
# File 'lib/babik/queryset/lib/association/foreign_association_chain.rb', line 12

def model
  @model
end

#selection_pathObject (readonly)

Returns the value of attribute selection_path.



12
13
14
# File 'lib/babik/queryset/lib/association/foreign_association_chain.rb', line 12

def selection_path
  @selection_path
end

#target_modelObject (readonly)

Returns the value of attribute target_model.



12
13
14
# File 'lib/babik/queryset/lib/association/foreign_association_chain.rb', line 12

def target_model
  @target_model
end

Instance Method Details

#_assert_association(association_model, association_name) ⇒ Association

Return an association or raise an exception if is not an allowed association

Returns:



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/babik/queryset/lib/association/foreign_association_chain.rb', line 76

def _assert_association(association_model, association_name)
  association = association_model.reflect_on_association(association_name.to_sym)

  # Check the association exists
  unless association
    raise "Bad selection path: #{@selection_path}. #{association_name} not found "\
          "in model #{association_model} when filtering #{@model} objects"
  end

  # Check the association is no a has-and belongs-to-many
  # These associations are discouraged by Rails Community
  if association.class == ActiveRecord::Reflection::HasAndBelongsToManyReflection
    raise "Relationship #{association.name} is has_and_belongs_to_many. Convert it to has_many-through"
  end

  # Valid association
  association
end

#_association_pass(association_i) ⇒ ActiveRecord::Base

Each one of the asssociation

Parameters:

  • association_i (AssociationReflection)

    ith association.

Returns:

  • (ActiveRecord::Base)

    target model of ith association.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/babik/queryset/lib/association/foreign_association_chain.rb', line 47

def _association_pass(association_i)
  # To one relationship
  if association_i.belongs_to? || association_i.has_one?
    @associations << association_i
    return association_i.klass
  end

  # Many-to-many with through relationship
  # The has-and-belongs-to-many relationships have been detected and filtered in _construct_association

  # Add model-through association (active_record -> klass)
  if association_i.through_reflection
    @associations << association_i.through_reflection
    # Add through-target association (through -> target)
    target_name = association_i.source_reflection_name
    through_model = association_i.through_reflection.klass
    through_target_association = through_model.reflect_on_association(target_name)
    @associations << through_target_association
    # The next association comes from target model
    return through_target_association.klass
  end

  # Add direct has_many association
  @associations << association_i
  Object.const_get(association_i.class_name)
end

#_init_association(model, association_name) ⇒ ActiveRecord::Base

Initialize association by name

Parameters:

  • model (ActiveRecord::Base)

    origin model of the association association_name

  • association_name (String, Symbol)

    association name.

Returns:

  • (ActiveRecord::Base)

    target model of ith association.



39
40
41
42
# File 'lib/babik/queryset/lib/association/foreign_association_chain.rb', line 39

def _init_association(model, association_name)
  association = _assert_association(model, association_name)
  _association_pass(association)
end

#_init_associationsObject

Init associations



26
27
28
29
30
31
32
33
# File 'lib/babik/queryset/lib/association/foreign_association_chain.rb', line 26

def _init_associations
  @associations = []
  associated_model_i = @model
  @association_path.each do |association_i_name|
    associated_model_i = _init_association(associated_model_i, association_i_name)
  end
  @target_model = associated_model_i
end