Class: Cuprum::Collections::Association

Inherits:
Resource show all
Defined in:
lib/cuprum/collections/association.rb

Overview

Class representing an association between resources.

Instance Attribute Summary collapse

Attributes included from Relations::Scope

#scope

Attributes included from Relations::Parameters

#name, #plural_name, #qualified_name, #singular_name

Attributes included from Relations::Options

#options

Instance Method Summary collapse

Methods included from Relations::Scope

#with_scope

Methods included from Relations::PrimaryKeys

#primary_key_name, #primary_key_type

Methods included from Relations::Cardinality

#plural?, #singular?

Methods included from Relations::Parameters

#entity_class, resolve_parameters, #resolve_parameters

Constructor Details

#initialize(entity_class: nil, name: nil, qualified_name: nil, singular_name: nil, **options) ⇒ Association

Returns a new instance of Association.

Parameters:

  • entity_class (Class, String) (defaults to: nil)

    the class of entity represented by the resource.

  • inverse (Cuprum::Collections::Resource)

    the inverse association, if any.

  • name (String) (defaults to: nil)

    the name of the resource.

  • qualified_name (String) (defaults to: nil)

    a scoped name for the resource.

  • singular_name (String) (defaults to: nil)

    the name of an entity in the resource.

  • options (Hash)

    additional options for the resource.

Options Hash (**options):

  • foreign_key_name (String)

    the name of the foreign key attribute.

  • inverse_class (Class, String)

    the class of the inverse association.

  • inverse_name (String, Symbol)

    the name of the inverse association.

  • plural (Boolean)

    if true, the resource represents a plural resource. Defaults to true. Can also be specified as :singular.

  • primary_key_name (String)

    the name of the primary key attribute. Defaults to 'id'.

  • singular_inverse_name (String, Symbol)

    the name of an entity in the inverse association.



33
34
35
36
37
# File 'lib/cuprum/collections/association.rb', line 33

def initialize(**params)
  super(**params.except(:inverse))

  @inverse = params[:inverse]
end

Instance Attribute Details

#inverseCuprum::Collections::Resource (readonly)

Returns the inverse association, if any.

Returns:



40
41
42
# File 'lib/cuprum/collections/association.rb', line 40

def inverse
  @inverse
end

Instance Method Details

#build_entities_query(*entities, allow_nil: false, deduplicate: true) ⇒ Proc

Generates a query for finding matching items.

Parameters:

  • entities (Array)

    the entities to query for.

  • allow_nil (Boolean) (defaults to: false)

    if true, allows for nil keys. Defaults to false.

  • deduplicate (Boolean) (defaults to: true)

    if true, removes duplicate keys before generating the query. Defaults to true.

Returns:

  • (Proc)

    the generated query.



51
52
53
54
55
56
57
58
59
60
61
# File 'lib/cuprum/collections/association.rb', line 51

def build_entities_query(*entities, allow_nil: false, deduplicate: true)
  keys =
    map_entities_to_keys(
      *entities,
      allow_nil:,
      deduplicate:,
      strict:      true
    )

  build_keys_query(*keys, allow_nil:, deduplicate: false)
end

#build_keys_query(*keys, allow_nil: false, deduplicate: true) ⇒ Proc

Generates a query for finding matching items by key.

Parameters:

  • keys (Array)

    the primary or foreign keys to query for.

  • allow_nil (Boolean) (defaults to: false)

    if true, allows for nil keys. Defaults to false.

  • deduplicate (Boolean) (defaults to: true)

    if true, removes duplicate keys before generating the query. Defaults to true.

Returns:

  • (Proc)

    the generated query.



72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/cuprum/collections/association.rb', line 72

def build_keys_query(*keys, allow_nil: false, deduplicate: true)
  keys     = keys.compact unless allow_nil
  keys     = keys.uniq    if deduplicate
  hash_key = query_key_name

  if keys.empty?
    ->(_) { {} }
  elsif keys.size == 1
    ->(_) { { hash_key => keys.first } }
  else
    ->(scope) { { hash_key => scope.one_of(keys) } }
  end
end

#foreign_key_nameString

Returns the name of the foreign key attribute.

Returns:

  • (String)

    the name of the foreign key attribute.



87
88
89
90
91
92
# File 'lib/cuprum/collections/association.rb', line 87

def foreign_key_name
  @foreign_key_name ||=
    options
      .fetch(:foreign_key_name) { default_foreign_key_name }
      &.to_s
end

#inverse_classClass

Returns the class of the inverse association, if any.

Returns:

  • (Class)

    the class of the inverse association, if any.



95
96
97
98
99
100
101
102
# File 'lib/cuprum/collections/association.rb', line 95

def inverse_class
  @inverse_class ||=
    options
      .fetch(:inverse_class) { inverse&.entity_class }
      .then do |value|
        value.is_a?(String) ? Object.const_get(value) : value
      end
end

#inverse_key_nameString

Returns the name of the inverse key.

Returns:

  • (String)

    the name of the inverse key.



105
106
107
108
109
# File 'lib/cuprum/collections/association.rb', line 105

def inverse_key_name
  return foreign_key_name if primary_key_query?

  primary_key_name
end

#inverse_nameString

Returns the name of the inverse association, if any.

Returns:

  • (String)

    the name of the inverse association, if any.



112
113
114
115
116
117
# File 'lib/cuprum/collections/association.rb', line 112

def inverse_name
  @inverse_name ||=
    options
      .fetch(:inverse_name) { default_inverse_name }
      &.to_s
end

#map_entities_to_keys(*entities, allow_nil: false, deduplicate: true, strict: true) ⇒ Array

Maps a list of entities to keys for performing a query.

Parameters:

  • entities (Array)

    the entities to query for.

  • allow_nil (Boolean) (defaults to: false)

    if true, allows for nil keys. Defaults to false.

  • deduplicate (Boolean) (defaults to: true)

    if true, removes duplicate keys before generating the query. Defaults to true.

  • strict (Boolean) (defaults to: true)

    if true, raises an exception if given an Array of keys instead of entities.

Returns:

  • (Array)

    the primary or foreign keys to query for.



130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/cuprum/collections/association.rb', line 130

def map_entities_to_keys(
  *entities,
  allow_nil:   false,
  deduplicate: true,
  strict:      true
)
  entities
    .compact
    .map { |entity| map_entity_to_key(entity, strict:) }
    .then { |keys| allow_nil ? keys : keys.compact }
    .then { |keys| deduplicate ? keys.uniq : keys }
end

#primary_key_query?Boolean

Returns true if the association queries by primary key, e.g. a :belongs_to association; false if the association queries by foreign key, e.g. a :has_one or :has_many association.

Returns:

  • (Boolean)

    true if the association queries by primary key, e.g. a :belongs_to association; false if the association queries by foreign key, e.g. a :has_one or :has_many association.



146
147
148
# File 'lib/cuprum/collections/association.rb', line 146

def primary_key_query?
  false
end

#query_key_nameString

Returns the name of the key used to perform the query.

Returns:

  • (String)

    the name of the key used to perform the query.



151
152
153
154
155
156
157
158
159
# File 'lib/cuprum/collections/association.rb', line 151

def query_key_name
  return primary_key_name if primary_key_query?

  if foreign_key_name.nil? || foreign_key_name.empty?
    raise ArgumentError, "foreign key name can't be blank"
  end

  foreign_key_name
end

#singular_inverse_nameString

Returns the name of an entity in the inverse association.

Returns:

  • (String)

    the name of an entity in the inverse association.



162
163
164
165
166
167
# File 'lib/cuprum/collections/association.rb', line 162

def singular_inverse_name
  @singular_inverse_name ||=
    options
      .fetch(:singular_inverse_name) { default_singular_inverse_name }
      &.to_s
end

#with_inverse(inverse) ⇒ Cuprum::Collections::Association

Creates a copy of the association with the specified inverse association.

Parameters:

Returns:



174
175
176
# File 'lib/cuprum/collections/association.rb', line 174

def with_inverse(inverse)
  dup.assign_inverse(inverse)
end