module Sequel::Plugins::AssociationFiltering::DatasetMethods
Constants
- COUNT_STAR
Public Instance Methods
association_exclude(association_name, &block)
click to toggle source
# File lib/sequel/plugins/association_filtering.rb, line 73 def association_exclude(association_name, &block) association_filter(association_name, invert: true, &block) end
association_filter( association_name, invert: false, **extra ) { |ds| ... }
click to toggle source
# File lib/sequel/plugins/association_filtering.rb, line 24 def association_filter( association_name, invert: false, **extra ) having_args = extra.slice(:at_least, :at_most, :exactly) case having_args.length when 0 # No-op when 1 having_arg = having_args.keys[0] having_value = having_args.values[0] raise Error, ":#{having_arg} must be an Integer if present" unless having_value.is_a?(Integer) else raise Error, "cannot pass more than one of :at_least, :at_most, and :exactly" end reflection = model.association_reflections.fetch(association_name) do raise Error, "association #{association_name} not found on model #{model}" end ds = _association_filter_dataset(reflection, group_by_remote: !!having_arg) ds = yield(ds) if block_given? cache_key = _association_filter_cache_key( reflection: reflection, extra: :"#{invert}_#{having_arg}_#{having_value}", ) ds.send :cached_dataset, cache_key do having_condition = case having_arg when :at_least then COUNT_STAR >= having_value when :at_most then COUNT_STAR <= having_value when :exactly then COUNT_STAR =~ having_value when nil then nil else raise Error, "Unexpected argument: #{having_arg.inspect}" end ds = ds.having(having_condition) if having_condition cond = ds.exists cond = Sequel.~(cond) if invert where(cond) end end
Private Instance Methods
_association_filter_cache_key(reflection:, extra: nil)
click to toggle source
# File lib/sequel/plugins/association_filtering.rb, line 119 def _association_filter_cache_key(reflection:, extra: nil) :"_association_filter_#{reflection[:model]}_#{reflection[:name]}_#{extra}" end
_association_filter_dataset(reflection, group_by_remote:)
click to toggle source
# File lib/sequel/plugins/association_filtering.rb, line 79 def _association_filter_dataset(reflection, group_by_remote:) cache_key = _association_filter_cache_key( reflection: reflection, extra: :"association_#{group_by_remote}" ) ds = reflection.associated_dataset ds.send(:cached_dataset, cache_key) do case t = reflection[:type] when :one_to_many local_keys = reflection.qualified_primary_key remote_keys = reflection.predicate_key when :many_to_one local_keys = reflection[:qualified_key] remote_keys = reflection.qualified_primary_key when :many_to_many local_keys = reflection.qualify_cur(reflection[:left_primary_key]) remote_keys = reflection.qualified_left_key else raise Error, "Unsupported reflection type: #{t}" end local_keys = Array(local_keys) remote_keys = Array(remote_keys) result = ds.where( remote_keys. zip(local_keys). map{|r,l| {r => l}}. inject{|a,b| Sequel.&(a, b)} ).select(1) result = result.group_by(*remote_keys) if group_by_remote result end end