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.
Name symbol for the _add internal association method
# File lib/sequel/model/associations.rb, line 25 def _add_method :"_add_#{singularize(self[:name])}" end
Name symbol for the _remove_all internal association method
# File lib/sequel/model/associations.rb, line 30 def _remove_all_method :"_remove_all_#{self[:name]}" end
Name symbol for the _remove internal association method
# File lib/sequel/model/associations.rb, line 35 def _remove_method :"_remove_#{singularize(self[:name])}" end
Name symbol for the _setter association method
# File lib/sequel/model/associations.rb, line 40 def _setter_method :"_#{self[:name]}=" end
Name symbol for the add association method
# File lib/sequel/model/associations.rb, line 45 def add_method :"add_#{singularize(self[:name])}" end
Apply all non-instance specific changes to the given dataset and return it.
# File lib/sequel/model/associations.rb, line 67 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 limit_to_single_row? ds = ds.eager(self[:eager]) if self[:eager] ds = ds.distinct if self[:distinct] ds end
Use DISTINCT ON and ORDER BY clauses to limit the results to the first record with matching keys.
# File lib/sequel/model/associations.rb, line 120 def apply_distinct_on_eager_limit_strategy(ds) keys = predicate_key ds.distinct(*keys).order_prepend(*keys) end
Apply all non-instance specific changes and the eager_block option to the given dataset and return it.
# File lib/sequel/model/associations.rb, line 85 def apply_eager_dataset_changes(ds) ds = apply_dataset_changes(ds) if block = self[:eager_block] ds = block.call(ds) end ds end
Apply the eager graph limit strategy to the dataset to graph into the current dataset, or return the dataset unmodified if no SQL limit strategy is needed.
# File lib/sequel/model/associations.rb, line 95 def apply_eager_graph_limit_strategy(strategy, ds) case strategy when :distinct_on apply_distinct_on_eager_limit_strategy(ds.order_prepend(*self[:order])) when :window_function apply_window_function_eager_limit_strategy(ds.order_prepend(*self[:order])).select(*ds.columns) else ds end end
Apply an eager limit strategy to the dataset, or return the dataset unmodified if it doesn't need an eager limit strategy.
# File lib/sequel/model/associations.rb, line 108 def apply_eager_limit_strategy(ds, strategy=eager_limit_strategy) case strategy when :distinct_on apply_distinct_on_eager_limit_strategy(ds) when :window_function apply_window_function_eager_limit_strategy(ds) else ds end end
If the ruby eager limit strategy is being used, slice the array using the slice range to return the object(s) at the correct offset/limit.
# File lib/sequel/model/associations.rb, line 146 def apply_ruby_eager_limit_strategy(rows) name = self[:name] if returns_array? range = slice_range rows.each{|o| o.associations[name] = o.associations[name][range] || []} elsif slice_range offset = slice_range.begin rows.each{|o| o.associations[name] = o.associations[name][offset]} end end
Use a window function to limit the results of the eager loading dataset.
# File lib/sequel/model/associations.rb, line 126 def apply_window_function_eager_limit_strategy(ds) rn = ds.row_number_column limit, offset = limit_and_offset ds = ds.unordered.select_append{|o| o.row_number{}.over(:partition=>predicate_key, :order=>ds.opts[:order]).as(rn)}.from_self ds = if !returns_array? ds.where(rn => offset ? offset+1 : 1) elsif offset offset += 1 if limit ds.where(rn => (offset...(offset+limit))) else ds.where{SQL::Identifier.new(rn) >= offset} end else ds.where{SQL::Identifier.new(rn) <= limit} end end
Whether the associations cache should use an array when storing the associated records during eager loading.
# File lib/sequel/model/associations.rb, line 159 def assign_singular? !returns_array? end
The class associated to the current model class via this association
# File lib/sequel/model/associations.rb, line 55 def associated_class cached_fetch(:class){constantize(self[:class_name])} end
The dataset associated via this association, with the non-instance specific changes already applied. This will be a joined dataset if the association requires joining tables.
# File lib/sequel/model/associations.rb, line 62 def associated_dataset cached_fetch(:_dataset){apply_dataset_changes(_associated_dataset)} end
Return an dataset that will load the appropriate associated objects for the given object using this association.
# File lib/sequel/model/associations.rb, line 196 def association_dataset_for(object) associated_dataset.where(predicate_keys.zip(predicate_key_values(object))) end
Proc used to create the association dataset method.
# File lib/sequel/model/associations.rb, line 202 def association_dataset_proc ASSOCIATION_DATASET_PROC end
Name symbol for association method, the same as the name of the association.
# File lib/sequel/model/associations.rb, line 50 def association_method self[:name] end
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.
# File lib/sequel/model/associations.rb, line 166 def can_have_associated_objects?(obj) true end
Whether you are able to clone from the given association type to the current association type, true by default only if the types match.
# File lib/sequel/model/associations.rb, line 172 def cloneable?(ref) ref[:type] == self[:type] end
Name symbol for the dataset association method
# File lib/sequel/model/associations.rb, line 177 def dataset_method :"#{self[:name]}_dataset" end
Whether the dataset needs a primary key to function, true by default.
# File lib/sequel/model/associations.rb, line 182 def dataset_need_primary_key? true end
Return the symbol used for the row number column if the window function eager limit strategy is being used, or nil otherwise.
# File lib/sequel/model/associations.rb, line 188 def delete_row_number_column(ds=associated_dataset) if eager_limit_strategy == :window_function ds.row_number_column end end
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.
# File lib/sequel/model/associations.rb, line 295 def eager_graph_lazy_dataset? true end
The eager_graph limit strategy to use for this dataset
# File lib/sequel/model/associations.rb, line 207 def eager_graph_limit_strategy(strategy) if self[:limit] || !returns_array? strategy = strategy[self[:name]] if strategy.is_a?(Hash) case strategy when true true_eager_graph_limit_strategy when Symbol strategy else if returns_array? || offset :ruby end end end end
The eager limit strategy to use for this dataset.
# File lib/sequel/model/associations.rb, line 224 def eager_limit_strategy cached_fetch(:_eager_limit_strategy) do if self[:limit] || !returns_array? case s = cached_fetch(:eager_limit_strategy){default_eager_limit_strategy} when true true_eager_limit_strategy else s end end end end
Eager load the associated objects using the hash of eager options, yielding each row to the block.
# File lib/sequel/model/associations.rb, line 239 def eager_load_results(eo, &block) rows = eo[:rows] initialize_association_cache(rows) unless eo[:initialize_rows] == false if eo[:id_map] ids = eo[:id_map].keys return ids if ids.empty? end strategy = eager_limit_strategy cascade = eo[:associations] if eo[:eager_block] || eo[:loader] == false strategy = true_eager_graph_limit_strategy if strategy == :union # Correlated subqueries are not supported for regular eager loading strategy = :ruby if strategy == :correlated_subquery objects = apply_eager_limit_strategy(eager_loading_dataset(eo), strategy).all elsif strategy == :union objects = [] ds = associated_dataset loader = union_eager_loader joiner = " UNION ALL " ids.each_slice(subqueries_per_union).each do |slice| objects.concat(ds.with_sql(slice.map{|k| loader.sql(*k)}.join(joiner)).to_a) end ds = ds.eager(cascade) if cascade ds.send(:post_load, objects) else loader = placeholder_eager_loader loader = loader.with_dataset{|dataset| dataset.eager(cascade)} if cascade objects = loader.all(ids) end objects.each(&block) if strategy == :ruby apply_ruby_eager_limit_strategy(rows) end end
The key to use for the key hash when eager loading
# File lib/sequel/model/associations.rb, line 277 def eager_loader_key self[:eager_loader_key] end
Alias of predicate_key, only for backwards compatibility.
# File lib/sequel/model/associations.rb, line 288 def eager_loading_predicate_key predicate_key end
By default associations do not need to select a key in an associated table to eagerly load.
# File lib/sequel/model/associations.rb, line 283 def eager_loading_use_associated_key? false end
Whether additional conditions should be added when using the filter by associations support.
# File lib/sequel/model/associations.rb, line 301 def filter_by_associations_add_conditions? self[:conditions] || self[:eager_block] || self[:limit] end
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.
# File lib/sequel/model/associations.rb, line 309 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
Whether to handle silent modification failure when adding/removing associated records, false by default.
# File lib/sequel/model/associations.rb, line 316 def handle_silent_modification_failure? false end
Initialize the associations cache for the current association for the given objects.
# File lib/sequel/model/associations.rb, line 321 def initialize_association_cache(objects) name = self[:name] if assign_singular? objects.each{|object| object.associations[name] = nil} else objects.each{|object| object.associations[name] = []} end end
The limit and offset for this association (returned as a two element array).
# File lib/sequel/model/associations.rb, line 331 def limit_and_offset if (v = self[:limit]).is_a?(Array) v else [v, nil] end end
Whether the associated object needs a primary key to be added/removed, false by default.
# File lib/sequel/model/associations.rb, line 341 def need_associated_primary_key? false end
A placeholder literalizer that can be used to lazily load the association. If one can't be used, returns nil.
# File lib/sequel/model/associations.rb, line 347 def placeholder_loader if use_placeholder_loader? cached_fetch(:placeholder_loader) do Sequel::Dataset::PlaceholderLiteralizer.loader(associated_dataset) do |pl, ds| ds.where(*predicate_keys.map{|k| SQL::BooleanExpression.new(:'=', k, pl.arg)}) end end end end
The values that predicate_keys should match for objects to be associated.
# File lib/sequel/model/associations.rb, line 363 def predicate_key_values(object) predicate_key_methods.map{|k| object.get_column_value(k)} end
The keys to use for loading of the regular dataset, as an array.
# File lib/sequel/model/associations.rb, line 358 def predicate_keys cached_fetch(:predicate_keys){Array(predicate_key)} end
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.
# File lib/sequel/model/associations.rb, line 370 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 col with the associated model's table name.
# File lib/sequel/model/associations.rb, line 382 def qualify_assoc(col) qualify(associated_class.table_name, col) end
Qualify col with the current model's table name.
# File lib/sequel/model/associations.rb, line 387 def qualify_cur(col) qualify(self[:model].table_name, col) end
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.
# File lib/sequel/model/associations.rb, line 397 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 ambiguous_reciprocal_type? possible_recips.first[:name] end end end
Whether the reciprocal of this association returns an array of objects instead of a single object, true by default.
# File lib/sequel/model/associations.rb, line 416 def reciprocal_array? true end
Name symbol for the remove_all_ association method
# File lib/sequel/model/associations.rb, line 421 def remove_all_method :"remove_all_#{self[:name]}" end
Whether associated objects need to be removed from the association before being destroyed in order to preserve referential integrity.
# File lib/sequel/model/associations.rb, line 427 def remove_before_destroy? true end
Name symbol for the remove_ association method
# File lib/sequel/model/associations.rb, line 432 def remove_method :"remove_#{singularize(self[:name])}" end
Whether to check that an object to be disassociated is already associated to this object, false by default.
# File lib/sequel/model/associations.rb, line 437 def remove_should_check_existing? false end
Whether this association returns an array of objects instead of a single object, true by default.
# File lib/sequel/model/associations.rb, line 443 def returns_array? true end
The columns to select when loading the association.
# File lib/sequel/model/associations.rb, line 448 def select self[:select] end
Whether to set the reciprocal association to self when loading associated records, false by default.
# File lib/sequel/model/associations.rb, line 454 def set_reciprocal_to_self? false end
Generated with the Darkfish Rdoc Generator 2.