Class: Sequel::Model::Associations::AssociationReflection

Inherits:
Hash
  • Object
show all
Includes:
Inflections
Defined in:
lib/sequel/model/associations.rb

Overview

AssociationReflection is a Hash subclass that keeps information on Sequel::Model associations. It provides methods to reduce internal code duplication. It should not be instantiated by the user.

Constant Summary

Constants included from Inflections

Inflections::CAMELIZE_CONVERT_REGEXP, Inflections::CAMELIZE_MODULE_REGEXP, Inflections::DASH, Inflections::DEMODULIZE_CONVERT_REGEXP, Inflections::EMPTY_STRING, Inflections::SLASH, Inflections::UNDERSCORE, Inflections::UNDERSCORE_CONVERT_REGEXP1, Inflections::UNDERSCORE_CONVERT_REGEXP2, Inflections::UNDERSCORE_CONVERT_REPLACE, Inflections::UNDERSCORE_MODULE_REGEXP, Inflections::VALID_CONSTANT_NAME_REGEXP

Instance Method Summary collapse

Methods included from Inflections

clear, irregular, plural, singular, uncountable

Methods inherited from Hash

#&, #case, #hstore, #pg_json, #sql_expr, #sql_negate, #sql_or, #|, #~

Instance Method Details

#_add_methodObject

Name symbol for the _add internal association method



22
23
24
# File 'lib/sequel/model/associations.rb', line 22

def _add_method
  :"_add_#{singularize(self[:name])}"
end

#_remove_all_methodObject

Name symbol for the _remove_all internal association method



27
28
29
# File 'lib/sequel/model/associations.rb', line 27

def _remove_all_method
  :"_remove_all_#{self[:name]}"
end

#_remove_methodObject

Name symbol for the _remove internal association method



32
33
34
# File 'lib/sequel/model/associations.rb', line 32

def _remove_method
  :"_remove_#{singularize(self[:name])}"
end

#_setter_methodObject

Name symbol for the _setter association method



37
38
39
# File 'lib/sequel/model/associations.rb', line 37

def _setter_method
  :"_#{self[:name]}="
end

#add_methodObject

Name symbol for the add association method



42
43
44
# File 'lib/sequel/model/associations.rb', line 42

def add_method
  :"add_#{singularize(self[:name])}"
end

#apply_dataset_changes(ds) ⇒ Object

Apply all non-instance specific changes to the given dataset and return it.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/sequel/model/associations.rb', line 63

def apply_dataset_changes(ds)
  ds.extend(AssociationDatasetMethods)
  ds.association_reflection = self
  self[:extend].each{|m| ds.extend(m)}
  ds = ds.select(*select) if select
  if c = self[:conditions]
    ds = (c.is_a?(Array) && !Sequel.condition_specifier?(c)) ? ds.where(*c) : ds.where(c)
  end
  ds = ds.order(*self[:order]) if self[:order]
  ds = ds.limit(*self[:limit]) if self[:limit]
  ds = ds.limit(1) if !returns_array? && self[:key]
  ds = ds.eager(*self[:eager]) if self[:eager]
  ds = ds.distinct if self[:distinct]
  ds
end

#associated_classObject

The class associated to the current model class via this association



52
53
54
# File 'lib/sequel/model/associations.rb', line 52

def associated_class
  cached_fetch(:class){constantize(self[:class_name])}
end

#associated_datasetObject

The dataset associated via this association, with the non-instance specific changes already applied.



58
59
60
# File 'lib/sequel/model/associations.rb', line 58

def associated_dataset
  cached_fetch(:_dataset){apply_dataset_changes(associated_class.dataset.clone)}
end

#association_methodObject

Name symbol for association method, the same as the name of the association.



47
48
49
# File 'lib/sequel/model/associations.rb', line 47

def association_method
  self[:name]
end

#can_have_associated_objects?(obj) ⇒ Boolean

Whether this association can have associated objects, given the current object. Should be false if obj cannot have associated objects because the necessary key columns are NULL.

Returns:

  • (Boolean)


82
83
84
# File 'lib/sequel/model/associations.rb', line 82

def can_have_associated_objects?(obj)
  true
end

#dataset_methodObject

Name symbol for the dataset association method



87
88
89
# File 'lib/sequel/model/associations.rb', line 87

def dataset_method
  :"#{self[:name]}_dataset"
end

#dataset_need_primary_key?Boolean

Whether the dataset needs a primary key to function, true by default.

Returns:

  • (Boolean)


92
93
94
# File 'lib/sequel/model/associations.rb', line 92

def dataset_need_primary_key?
  true
end

#eager_graph_lazy_dataset?Boolean

Whether to eagerly graph a lazy dataset, true by default. If this is false, the association won’t respect the :eager_graph option when loading the association for a single record.

Returns:

  • (Boolean)


136
137
138
# File 'lib/sequel/model/associations.rb', line 136

def eager_graph_lazy_dataset?
  true
end

#eager_limit_strategyObject

The eager limit strategy to use for this dataset.



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/sequel/model/associations.rb', line 97

def eager_limit_strategy
  cached_fetch(:_eager_limit_strategy) do
    if self[:limit]
      case s = cached_fetch(:eager_limit_strategy){self[:model].default_eager_limit_strategy || :ruby}
      when true
        ds = associated_class.dataset
        if ds.supports_window_functions?
          :window_function
        else
          :ruby
        end
      else
        s
      end
    else
      nil
    end
  end
end

#eager_loader_keyObject

The key to use for the key hash when eager loading



118
119
120
# File 'lib/sequel/model/associations.rb', line 118

def eager_loader_key
  self[:eager_loader_key]
end

#eager_loading_predicate_keyObject

Alias of predicate_key, only for backwards compatibility.



129
130
131
# File 'lib/sequel/model/associations.rb', line 129

def eager_loading_predicate_key
  predicate_key
end

#eager_loading_use_associated_key?Boolean

By default associations do not need to select a key in an associated table to eagerly load.

Returns:

  • (Boolean)


124
125
126
# File 'lib/sequel/model/associations.rb', line 124

def eager_loading_use_associated_key?
  false
end

#filter_by_associations_add_conditions?Boolean

Whether additional conditions should be added when using the filter by associations support.

Returns:

  • (Boolean)


142
143
144
# File 'lib/sequel/model/associations.rb', line 142

def filter_by_associations_add_conditions?
  self[:conditions] || self[:eager_block]
end

#filter_by_associations_conditions_expression(obj) ⇒ Object

The expression to use for the additional conditions to be added for the filter by association support, when the association itself is filtered. Works by using a subquery to test that the objects passed also meet the association filter criteria.



150
151
152
153
# File 'lib/sequel/model/associations.rb', line 150

def filter_by_associations_conditions_expression(obj)
  ds = filter_by_associations_conditions_dataset.where(filter_by_associations_conditions_subquery_conditions(obj))
  {filter_by_associations_conditions_key=>ds}
end

#limit_and_offsetObject

The limit and offset for this association (returned as a two element array).



156
157
158
159
160
161
162
# File 'lib/sequel/model/associations.rb', line 156

def limit_and_offset
  if (v = self[:limit]).is_a?(Array)
    v
  else
    [v, nil]
  end
end

#need_associated_primary_key?Boolean

Whether the associated object needs a primary key to be added/removed, false by default.

Returns:

  • (Boolean)


166
167
168
# File 'lib/sequel/model/associations.rb', line 166

def need_associated_primary_key?
  false
end

#predicate_keysObject

The keys to use for loading of the regular dataset, as an array.



171
172
173
# File 'lib/sequel/model/associations.rb', line 171

def predicate_keys
  cached_fetch(:predicate_keys){Array(predicate_key)}
end

#qualify(table, col) ⇒ Object

Qualify col with the given table name. If col is an array of columns, return an array of qualified columns. Only qualifies Symbols and SQL::Identifier values, other values are not modified.



178
179
180
181
182
183
184
185
186
187
# File 'lib/sequel/model/associations.rb', line 178

def qualify(table, col)
  transform(col) do |k|
    case k
    when Symbol, SQL::Identifier
      SQL::QualifiedIdentifier.new(table, k)
    else
      Sequel::Qualifier.new(self[:model].dataset, table).transform(k)
    end
  end
end

#qualify_assoc(col) ⇒ Object

Qualify col with the associated model’s table name.



190
191
192
# File 'lib/sequel/model/associations.rb', line 190

def qualify_assoc(col)
  qualify(associated_class.table_name, col)
end

#qualify_cur(col) ⇒ Object

Qualify col with the current model’s table name.



195
196
197
# File 'lib/sequel/model/associations.rb', line 195

def qualify_cur(col)
  qualify(self[:model].table_name, col)
end

#reciprocalObject

Returns the reciprocal association variable, if one exists. The reciprocal association is the association in the associated class that is the opposite of the current association. For example, Album.many_to_one :artist and Artist.one_to_many :albums are reciprocal associations. This information is to populate reciprocal associations. For example, when you do this_artist.add_album(album) it sets album.artist to this_artist.



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/sequel/model/associations.rb', line 205

def reciprocal
  cached_fetch(:reciprocal) do
    possible_recips = []

    associated_class.all_association_reflections.each do |assoc_reflect|
      if reciprocal_association?(assoc_reflect)
        possible_recips << assoc_reflect
      end
    end

    if possible_recips.length == 1
      cached_set(:reciprocal_type, possible_recips.first[:type]) if reciprocal_type.is_a?(Array)
      possible_recips.first[:name]
    end
  end
end

#reciprocal_array?Boolean

Whether the reciprocal of this association returns an array of objects instead of a single object, true by default.

Returns:

  • (Boolean)


224
225
226
# File 'lib/sequel/model/associations.rb', line 224

def reciprocal_array?
  true
end

#remove_all_methodObject

Name symbol for the remove_all_ association method



229
230
231
# File 'lib/sequel/model/associations.rb', line 229

def remove_all_method
  :"remove_all_#{self[:name]}"
end

#remove_before_destroy?Boolean

Whether associated objects need to be removed from the association before being destroyed in order to preserve referential integrity.

Returns:

  • (Boolean)


235
236
237
# File 'lib/sequel/model/associations.rb', line 235

def remove_before_destroy?
  true
end

#remove_methodObject

Name symbol for the remove_ association method



240
241
242
# File 'lib/sequel/model/associations.rb', line 240

def remove_method
  :"remove_#{singularize(self[:name])}"
end

#remove_should_check_existing?Boolean

Whether to check that an object to be disassociated is already associated to this object, false by default.

Returns:

  • (Boolean)


245
246
247
# File 'lib/sequel/model/associations.rb', line 245

def remove_should_check_existing?
  false
end

#returns_array?Boolean

Whether this association returns an array of objects instead of a single object, true by default.

Returns:

  • (Boolean)


251
252
253
# File 'lib/sequel/model/associations.rb', line 251

def returns_array?
  true
end

#selectObject

The columns to select when loading the association.



256
257
258
# File 'lib/sequel/model/associations.rb', line 256

def select
  self[:select]
end

#set_reciprocal_to_self?Boolean

Whether to set the reciprocal association to self when loading associated records, false by default.

Returns:

  • (Boolean)


262
263
264
# File 'lib/sequel/model/associations.rb', line 262

def set_reciprocal_to_self?
  false
end

#setter_methodObject

Name symbol for the setter association method



267
268
269
# File 'lib/sequel/model/associations.rb', line 267

def setter_method
  :"#{self[:name]}="
end

#slice_rangeObject

The range used for slicing when using the :ruby eager limit strategy.



272
273
274
275
276
277
# File 'lib/sequel/model/associations.rb', line 272

def slice_range
  limit, offset = limit_and_offset
  if limit || offset
    (offset||0)..(limit ? (offset||0)+limit-1 : -1)
  end
end