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 inherited from Relation

#options

Attributes included from Relation::Parameters

#name, #plural_name, #qualified_name, #singular_name

Instance Method Summary collapse

Methods inherited from Resource

#resource_class, #resource_name, #singular_resource_name

Methods included from Relation::PrimaryKeys

#primary_key_name, #primary_key_type

Methods included from Relation::Disambiguation

disambiguate_keyword, #disambiguate_keyword, resolve_parameters, #resolve_parameters

Methods included from Relation::Cardinality

#plural?, #singular?

Methods included from Relation::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
38
39
40
# File 'lib/cuprum/collections/association.rb', line 33

def initialize(**params)
  params = disambiguate_keyword(params, :entity_class, :association_class)
  params = disambiguate_keyword(params, :name, :association_name)

  @inverse = params.delete(:inverse)

  super(**params)
end

Instance Attribute Details

#inverseCuprum::Collections::Resource (readonly)

Returns the inverse association, if any.

Returns:



43
44
45
# File 'lib/cuprum/collections/association.rb', line 43

def inverse
  @inverse
end

Instance Method Details

#association_classClass

Returns the class of entity represented by the resource.

Returns:

  • (Class)

    the class of entity represented by the resource.



46
47
48
49
50
51
# File 'lib/cuprum/collections/association.rb', line 46

def association_class
  tools.core_tools.deprecate '#association_class method',
    message: 'Use #entity_class instead'

  entity_class
end

#association_nameString

Returns the name of the resource.

Returns:

  • (String)

    the name of the resource.



54
55
56
57
58
59
# File 'lib/cuprum/collections/association.rb', line 54

def association_name
  tools.core_tools.deprecate '#association_name method',
    message: 'Use #name instead'

  name
end

#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.



70
71
72
73
74
75
76
77
78
79
80
# File 'lib/cuprum/collections/association.rb', line 70

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

  build_keys_query(*keys, allow_nil: 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.



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

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
    -> { { hash_key => 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.



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

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.



114
115
116
117
118
119
120
121
# File 'lib/cuprum/collections/association.rb', line 114

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.



124
125
126
127
128
# File 'lib/cuprum/collections/association.rb', line 124

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.



131
132
133
134
135
136
# File 'lib/cuprum/collections/association.rb', line 131

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.



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

def map_entities_to_keys(
  *entities,
  allow_nil:   false,
  deduplicate: true,
  strict:      true
)
  entities
    .compact
    .map { |entity| map_entity_to_key(entity, strict: 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.



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

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.



170
171
172
173
174
175
176
177
178
# File 'lib/cuprum/collections/association.rb', line 170

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.



181
182
183
184
185
186
# File 'lib/cuprum/collections/association.rb', line 181

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:



193
194
195
# File 'lib/cuprum/collections/association.rb', line 193

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