/usr/lib/ruby/vendor_ruby/active_record/relation/spawn_methods.rb is in ruby-activerecord-3.2 3.2.16-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | require 'active_support/core_ext/object/blank'
module ActiveRecord
module SpawnMethods
def merge(r)
return self unless r
return to_a & r if r.is_a?(Array)
merged_relation = clone
r = r.with_default_scope if r.default_scoped? && r.klass != klass
Relation::ASSOCIATION_METHODS.each do |method|
value = r.send(:"#{method}_values")
unless value.empty?
if method == :includes
merged_relation = merged_relation.includes(value)
else
merge_relation_method(merged_relation, method, value)
end
end
end
(Relation::MULTI_VALUE_METHODS - [:joins, :where, :order]).each do |method|
value = r.send(:"#{method}_values")
merge_relation_method(merged_relation, method, value) if value.present?
end
merge_joins(merged_relation, r)
merged_wheres = @where_values + r.where_values
unless @where_values.empty?
# Remove duplicate ARel attributes. Last one wins.
seen = Hash.new { |h,table| h[table] = {} }
merged_wheres = merged_wheres.reverse.reject { |w|
nuke = false
if w.respond_to?(:operator) && w.operator == :== &&
w.left.respond_to?(:relation)
name = w.left.name
table = w.left.relation.name
nuke = seen[table][name]
seen[table][name] = true
end
nuke
}.reverse
end
merged_relation.where_values = merged_wheres
(Relation::SINGLE_VALUE_METHODS - [:lock, :create_with, :reordering]).each do |method|
value = r.send(:"#{method}_value")
merged_relation.send(:"#{method}_value=", value) unless value.nil?
end
merged_relation.lock_value = r.lock_value unless merged_relation.lock_value
merged_relation = merged_relation.create_with(r.create_with_value) unless r.create_with_value.empty?
if (r.reordering_value)
# override any order specified in the original relation
merged_relation.reordering_value = true
merged_relation.order_values = r.order_values
else
# merge in order_values from r
merged_relation.order_values += r.order_values
end
# Apply scope extension modules
merged_relation.send :apply_modules, r.extensions
merged_relation
end
# Removes from the query the condition(s) specified in +skips+.
#
# Example:
#
# 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
#
def except(*skips)
result = self.class.new(@klass, table)
result.default_scoped = default_scoped
((Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS) - skips).each do |method|
result.send(:"#{method}_values=", send(:"#{method}_values"))
end
(Relation::SINGLE_VALUE_METHODS - skips).each do |method|
result.send(:"#{method}_value=", send(:"#{method}_value"))
end
# Apply scope extension modules
result.send(:apply_modules, extensions)
result
end
# Removes any condition from the query other than the one(s) specified in +onlies+.
#
# Example:
#
# Post.order('id asc').only(:where) # discards the order condition
# Post.order('id asc').only(:where, :order) # uses the specified order
#
def only(*onlies)
result = self.class.new(@klass, table)
result.default_scoped = default_scoped
((Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS) & onlies).each do |method|
result.send(:"#{method}_values=", send(:"#{method}_values"))
end
(Relation::SINGLE_VALUE_METHODS & onlies).each do |method|
result.send(:"#{method}_value=", send(:"#{method}_value"))
end
# Apply scope extension modules
result.send(:apply_modules, extensions)
result
end
VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :extend,
:order, :select, :readonly, :group, :having, :from, :lock ]
def apply_finder_options(options)
relation = clone
return relation unless options
options.assert_valid_keys(VALID_FIND_OPTIONS)
finders = options.dup
finders.delete_if { |key, value| value.nil? && key != :limit }
([:joins, :select, :group, :order, :having, :limit, :offset, :from, :lock, :readonly] & finders.keys).each do |finder|
relation = relation.send(finder, finders[finder])
end
relation = relation.where(finders[:conditions]) if options.has_key?(:conditions)
relation = relation.includes(finders[:include]) if options.has_key?(:include)
relation = relation.extending(finders[:extend]) if options.has_key?(:extend)
relation
end
private
def merge_joins(relation, other)
values = other.joins_values
return if values.blank?
if other.klass >= relation.klass
relation.joins_values += values
else
joins_dependency, rest = values.partition do |join|
case join
when Hash, Symbol, Array
true
else
false
end
end
join_dependency = ActiveRecord::Associations::JoinDependency.new(
other.klass,
joins_dependency,
[]
)
relation.joins_values += join_dependency.join_associations + rest
end
end
def merge_relation_method(relation, method, value)
relation.send(:"#{method}_values=", relation.send(:"#{method}_values") + value)
end
end
end
|