Module: ActiveRecord::SpawnMethods

Included in:
Relation
Defined in:
lib/active_record/relation/spawn_methods.rb

Instance Method Summary collapse

Instance Method Details

#except(*skips) ⇒ Object

Removes from the query the condition(s) specified in skips.

Post.order('id asc').except(:order)                  # discards the order condition
Post.where('id > 10').order('id asc').except(:where) # discards the where condition but keeps the order


75
76
77
# File 'lib/active_record/relation/spawn_methods.rb', line 75

def except(*skips)
  relation_with values.except(*skips)
end

#merge(other, *rest) ⇒ Object

Merges in the conditions from other, if other is an ActiveRecord::Relation. Returns an array representing the intersection of the resulting records with other, if other is an array.

Post.where(published: true).joins(:comments).merge( Comment.where(spam: false) )
# Performs a single join query with both where conditions.

recent_posts = Post.order('created_at DESC').first(5)
Post.where(published: true).merge(recent_posts)
# Returns the intersection of all published posts with the 5 most recently created posts.
# (This is just an example. You'd probably want to do this with a single query!)

Procs will be evaluated by merge:

Post.where(published: true).merge(-> { joins(:comments) })
# => Post.where(published: true).joins(:comments)

This is mainly intended for sharing common conditions between multiple associations.

For conditions that exist in both relations, those from other will take precedence. To find the intersection of two relations, use QueryMethods#and.



33
34
35
36
37
38
39
40
41
# File 'lib/active_record/relation/spawn_methods.rb', line 33

def merge(other, *rest)
  if other.is_a?(Array)
    records & other
  elsif other
    spawn.merge!(other, *rest)
  else
    raise ArgumentError, "invalid argument: #{other.inspect}."
  end
end

#merge!(other, *rest) ⇒ Object

:nodoc:



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/active_record/relation/spawn_methods.rb', line 43

def merge!(other, *rest) # :nodoc:
  options = rest.extract_options!

  if options.key?(:rewhere)
    if options[:rewhere]
      ActiveRecord.deprecator.warn(<<-MSG.squish)
        Specifying `Relation#merge(rewhere: true)` is deprecated, as that has now been
        the default since Rails 7.0. Setting the rewhere option will error in Rails 7.2
      MSG
    else
      ActiveRecord.deprecator.warn(<<-MSG.squish)
        `Relation#merge(rewhere: false)` is deprecated without replacement,
        and will be removed in Rails 7.2
      MSG
    end
  end

  if other.is_a?(Hash)
    Relation::HashMerger.new(self, other, options[:rewhere]).merge
  elsif other.is_a?(Relation)
    Relation::Merger.new(self, other, options[:rewhere]).merge
  elsif other.respond_to?(:to_proc)
    instance_exec(&other)
  else
    raise ArgumentError, "#{other.inspect} is not an ActiveRecord::Relation"
  end
end

#only(*onlies) ⇒ Object

Removes any condition from the query other than the one(s) specified in onlies.

Post.order('id asc').only(:where)         # discards the order condition
Post.order('id asc').only(:where, :order) # uses the specified order


83
84
85
# File 'lib/active_record/relation/spawn_methods.rb', line 83

def only(*onlies)
  relation_with values.slice(*onlies)
end

#spawnObject

:nodoc:



9
10
11
# File 'lib/active_record/relation/spawn_methods.rb', line 9

def spawn # :nodoc:
  already_in_scope?(klass.scope_registry) ? klass.all : clone
end