square-activerecord 3.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +6140 -0
- data/README.rdoc +222 -0
- data/examples/associations.png +0 -0
- data/examples/performance.rb +179 -0
- data/examples/simple.rb +14 -0
- data/lib/active_record.rb +124 -0
- data/lib/active_record/aggregations.rb +277 -0
- data/lib/active_record/association_preload.rb +430 -0
- data/lib/active_record/associations.rb +2307 -0
- data/lib/active_record/associations/association_collection.rb +572 -0
- data/lib/active_record/associations/association_proxy.rb +299 -0
- data/lib/active_record/associations/belongs_to_association.rb +91 -0
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +82 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +143 -0
- data/lib/active_record/associations/has_many_association.rb +128 -0
- data/lib/active_record/associations/has_many_through_association.rb +115 -0
- data/lib/active_record/associations/has_one_association.rb +143 -0
- data/lib/active_record/associations/has_one_through_association.rb +40 -0
- data/lib/active_record/associations/through_association_scope.rb +154 -0
- data/lib/active_record/attribute_methods.rb +60 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +30 -0
- data/lib/active_record/attribute_methods/dirty.rb +95 -0
- data/lib/active_record/attribute_methods/primary_key.rb +56 -0
- data/lib/active_record/attribute_methods/query.rb +39 -0
- data/lib/active_record/attribute_methods/read.rb +145 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +64 -0
- data/lib/active_record/attribute_methods/write.rb +43 -0
- data/lib/active_record/autosave_association.rb +369 -0
- data/lib/active_record/base.rb +1904 -0
- data/lib/active_record/callbacks.rb +284 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +364 -0
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +113 -0
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +57 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +333 -0
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +81 -0
- data/lib/active_record/connection_adapters/abstract/quoting.rb +73 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +739 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +539 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +217 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +657 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1031 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -0
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +401 -0
- data/lib/active_record/counter_cache.rb +115 -0
- data/lib/active_record/dynamic_finder_match.rb +56 -0
- data/lib/active_record/dynamic_scope_match.rb +23 -0
- data/lib/active_record/errors.rb +172 -0
- data/lib/active_record/fixtures.rb +1006 -0
- data/lib/active_record/locale/en.yml +40 -0
- data/lib/active_record/locking/optimistic.rb +172 -0
- data/lib/active_record/locking/pessimistic.rb +55 -0
- data/lib/active_record/log_subscriber.rb +48 -0
- data/lib/active_record/migration.rb +617 -0
- data/lib/active_record/named_scope.rb +138 -0
- data/lib/active_record/nested_attributes.rb +419 -0
- data/lib/active_record/observer.rb +125 -0
- data/lib/active_record/persistence.rb +290 -0
- data/lib/active_record/query_cache.rb +36 -0
- data/lib/active_record/railtie.rb +91 -0
- data/lib/active_record/railties/controller_runtime.rb +38 -0
- data/lib/active_record/railties/databases.rake +512 -0
- data/lib/active_record/reflection.rb +411 -0
- data/lib/active_record/relation.rb +394 -0
- data/lib/active_record/relation/batches.rb +89 -0
- data/lib/active_record/relation/calculations.rb +295 -0
- data/lib/active_record/relation/finder_methods.rb +363 -0
- data/lib/active_record/relation/predicate_builder.rb +48 -0
- data/lib/active_record/relation/query_methods.rb +303 -0
- data/lib/active_record/relation/spawn_methods.rb +132 -0
- data/lib/active_record/schema.rb +59 -0
- data/lib/active_record/schema_dumper.rb +195 -0
- data/lib/active_record/serialization.rb +60 -0
- data/lib/active_record/serializers/xml_serializer.rb +244 -0
- data/lib/active_record/session_store.rb +340 -0
- data/lib/active_record/test_case.rb +67 -0
- data/lib/active_record/timestamp.rb +88 -0
- data/lib/active_record/transactions.rb +359 -0
- data/lib/active_record/validations.rb +84 -0
- data/lib/active_record/validations/associated.rb +48 -0
- data/lib/active_record/validations/uniqueness.rb +190 -0
- data/lib/active_record/version.rb +10 -0
- data/lib/rails/generators/active_record.rb +19 -0
- data/lib/rails/generators/active_record/migration.rb +15 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +25 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +17 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +38 -0
- data/lib/rails/generators/active_record/model/templates/migration.rb +16 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +5 -0
- data/lib/rails/generators/active_record/model/templates/module.rb +5 -0
- data/lib/rails/generators/active_record/observer/observer_generator.rb +15 -0
- data/lib/rails/generators/active_record/observer/templates/observer.rb +2 -0
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +24 -0
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +16 -0
- metadata +223 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class PredicateBuilder
|
3
|
+
|
4
|
+
def initialize(engine)
|
5
|
+
@engine = engine
|
6
|
+
end
|
7
|
+
|
8
|
+
def build_from_hash(attributes, default_table)
|
9
|
+
predicates = attributes.map do |column, value|
|
10
|
+
table = default_table
|
11
|
+
|
12
|
+
if value.is_a?(Hash)
|
13
|
+
table = Arel::Table.new(column, :engine => @engine)
|
14
|
+
build_from_hash(value, table)
|
15
|
+
else
|
16
|
+
column = column.to_s
|
17
|
+
|
18
|
+
if column.include?('.')
|
19
|
+
table_name, column = column.split('.', 2)
|
20
|
+
table = Arel::Table.new(table_name, :engine => @engine)
|
21
|
+
end
|
22
|
+
|
23
|
+
attribute = table[column] || Arel::Attribute.new(table, column)
|
24
|
+
|
25
|
+
case value
|
26
|
+
when Array, ActiveRecord::Associations::AssociationCollection, ActiveRecord::Relation
|
27
|
+
values = value.to_a.map { |x|
|
28
|
+
x.is_a?(ActiveRecord::Base) ? x.id : x
|
29
|
+
}
|
30
|
+
attribute.in(values)
|
31
|
+
when Range, Arel::Relation
|
32
|
+
attribute.in(value)
|
33
|
+
when ActiveRecord::Base
|
34
|
+
attribute.eq(value.id)
|
35
|
+
when Class
|
36
|
+
# FIXME: I think we need to deprecate this behavior
|
37
|
+
attribute.eq(value.name)
|
38
|
+
else
|
39
|
+
attribute.eq(value)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
predicates.flatten
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,303 @@
|
|
1
|
+
require 'active_support/core_ext/array/wrap'
|
2
|
+
require 'active_support/core_ext/object/blank'
|
3
|
+
|
4
|
+
module ActiveRecord
|
5
|
+
module QueryMethods
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
attr_accessor :includes_values, :eager_load_values, :preload_values,
|
9
|
+
:select_values, :group_values, :order_values, :reorder_flag, :joins_values, :where_values, :having_values,
|
10
|
+
:limit_value, :offset_value, :lock_value, :readonly_value, :create_with_value, :from_value
|
11
|
+
|
12
|
+
def includes(*args)
|
13
|
+
args.reject! {|a| a.blank? }
|
14
|
+
|
15
|
+
return clone if args.empty?
|
16
|
+
|
17
|
+
relation = clone
|
18
|
+
relation.includes_values = (relation.includes_values + args).flatten.uniq
|
19
|
+
relation
|
20
|
+
end
|
21
|
+
|
22
|
+
def eager_load(*args)
|
23
|
+
relation = clone
|
24
|
+
relation.eager_load_values += args unless args.blank?
|
25
|
+
relation
|
26
|
+
end
|
27
|
+
|
28
|
+
def preload(*args)
|
29
|
+
relation = clone
|
30
|
+
relation.preload_values += args unless args.blank?
|
31
|
+
relation
|
32
|
+
end
|
33
|
+
|
34
|
+
def select(value = Proc.new)
|
35
|
+
if block_given?
|
36
|
+
to_a.select {|*block_args| value.call(*block_args) }
|
37
|
+
else
|
38
|
+
relation = clone
|
39
|
+
relation.select_values += Array.wrap(value)
|
40
|
+
relation
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def group(*args)
|
45
|
+
relation = clone
|
46
|
+
relation.group_values += args.flatten unless args.blank?
|
47
|
+
relation
|
48
|
+
end
|
49
|
+
|
50
|
+
def order(*args)
|
51
|
+
relation = clone
|
52
|
+
relation.order_values += args.flatten unless args.blank?
|
53
|
+
relation
|
54
|
+
end
|
55
|
+
|
56
|
+
def reorder(*args)
|
57
|
+
relation = clone
|
58
|
+
unless args.blank?
|
59
|
+
relation.order_values = args
|
60
|
+
relation.reorder_flag = true
|
61
|
+
end
|
62
|
+
relation
|
63
|
+
end
|
64
|
+
|
65
|
+
def joins(*args)
|
66
|
+
relation = clone
|
67
|
+
|
68
|
+
args.flatten!
|
69
|
+
relation.joins_values += args unless args.blank?
|
70
|
+
|
71
|
+
relation
|
72
|
+
end
|
73
|
+
|
74
|
+
def where(opts, *rest)
|
75
|
+
relation = clone
|
76
|
+
relation.where_values += build_where(opts, rest) unless opts.blank?
|
77
|
+
relation
|
78
|
+
end
|
79
|
+
|
80
|
+
def having(*args)
|
81
|
+
relation = clone
|
82
|
+
relation.having_values += build_where(*args) unless args.blank?
|
83
|
+
relation
|
84
|
+
end
|
85
|
+
|
86
|
+
def limit(value)
|
87
|
+
relation = clone
|
88
|
+
relation.limit_value = value
|
89
|
+
relation
|
90
|
+
end
|
91
|
+
|
92
|
+
def offset(value)
|
93
|
+
relation = clone
|
94
|
+
relation.offset_value = value
|
95
|
+
relation
|
96
|
+
end
|
97
|
+
|
98
|
+
def lock(locks = true)
|
99
|
+
relation = clone
|
100
|
+
|
101
|
+
case locks
|
102
|
+
when String, TrueClass, NilClass
|
103
|
+
relation.lock_value = locks || true
|
104
|
+
else
|
105
|
+
relation.lock_value = false
|
106
|
+
end
|
107
|
+
|
108
|
+
relation
|
109
|
+
end
|
110
|
+
|
111
|
+
def readonly(value = true)
|
112
|
+
relation = clone
|
113
|
+
relation.readonly_value = value
|
114
|
+
relation
|
115
|
+
end
|
116
|
+
|
117
|
+
def create_with(value)
|
118
|
+
relation = clone
|
119
|
+
relation.create_with_value = value
|
120
|
+
relation
|
121
|
+
end
|
122
|
+
|
123
|
+
def from(value)
|
124
|
+
relation = clone
|
125
|
+
relation.from_value = value
|
126
|
+
relation
|
127
|
+
end
|
128
|
+
|
129
|
+
def extending(*modules, &block)
|
130
|
+
modules << Module.new(&block) if block_given?
|
131
|
+
|
132
|
+
relation = clone
|
133
|
+
relation.send(:apply_modules, modules.flatten)
|
134
|
+
relation
|
135
|
+
end
|
136
|
+
|
137
|
+
def reverse_order
|
138
|
+
order_clause = arel.order_clauses.join(', ')
|
139
|
+
relation = except(:order)
|
140
|
+
|
141
|
+
order = order_clause.blank? ?
|
142
|
+
"#{@klass.table_name}.#{@klass.primary_key} DESC" :
|
143
|
+
reverse_sql_order(order_clause)
|
144
|
+
|
145
|
+
relation.order(Arel.sql(order))
|
146
|
+
end
|
147
|
+
|
148
|
+
def arel
|
149
|
+
@arel ||= build_arel
|
150
|
+
end
|
151
|
+
|
152
|
+
def custom_join_sql(*joins)
|
153
|
+
arel = table.select_manager
|
154
|
+
|
155
|
+
joins.each do |join|
|
156
|
+
next if join.blank?
|
157
|
+
|
158
|
+
@implicit_readonly = true
|
159
|
+
|
160
|
+
case join
|
161
|
+
when Array
|
162
|
+
join = Arel.sql(join.join(' ')) if array_of_strings?(join)
|
163
|
+
when String
|
164
|
+
join = Arel.sql(join)
|
165
|
+
end
|
166
|
+
|
167
|
+
arel.join(join)
|
168
|
+
end
|
169
|
+
|
170
|
+
arel.join_sql
|
171
|
+
end
|
172
|
+
|
173
|
+
def build_arel
|
174
|
+
arel = table
|
175
|
+
|
176
|
+
arel = build_joins(arel, @joins_values) unless @joins_values.empty?
|
177
|
+
|
178
|
+
arel = collapse_wheres(arel, (@where_values - ['']).uniq)
|
179
|
+
|
180
|
+
arel = arel.having(*@having_values.uniq.reject{|h| h.blank?}) unless @having_values.empty?
|
181
|
+
|
182
|
+
arel = arel.take(connection.sanitize_limit(@limit_value)) if @limit_value
|
183
|
+
arel = arel.skip(@offset_value) if @offset_value
|
184
|
+
|
185
|
+
arel = arel.group(*@group_values.uniq.reject{|g| g.blank?}) unless @group_values.empty?
|
186
|
+
|
187
|
+
arel = arel.order(*@order_values.uniq.reject{|o| o.blank?}) unless @order_values.empty?
|
188
|
+
|
189
|
+
arel = build_select(arel, @select_values.uniq)
|
190
|
+
|
191
|
+
arel = arel.from(@from_value) if @from_value
|
192
|
+
arel = arel.lock(@lock_value) if @lock_value
|
193
|
+
|
194
|
+
arel
|
195
|
+
end
|
196
|
+
|
197
|
+
private
|
198
|
+
|
199
|
+
def collapse_wheres(arel, wheres)
|
200
|
+
equalities = wheres.grep(Arel::Nodes::Equality)
|
201
|
+
|
202
|
+
groups = equalities.group_by do |equality|
|
203
|
+
equality.left
|
204
|
+
end
|
205
|
+
|
206
|
+
groups.each do |_, eqls|
|
207
|
+
test = eqls.inject(eqls.shift) do |memo, expr|
|
208
|
+
memo.and(expr)
|
209
|
+
end
|
210
|
+
arel = arel.where(test)
|
211
|
+
end
|
212
|
+
|
213
|
+
(wheres - equalities).each do |where|
|
214
|
+
where = Arel.sql(where) if String === where
|
215
|
+
arel = arel.where(Arel::Nodes::Grouping.new(where))
|
216
|
+
end
|
217
|
+
arel
|
218
|
+
end
|
219
|
+
|
220
|
+
def build_where(opts, other = [])
|
221
|
+
case opts
|
222
|
+
when String, Array
|
223
|
+
[@klass.send(:sanitize_sql, other.empty? ? opts : ([opts] + other))]
|
224
|
+
when Hash
|
225
|
+
attributes = @klass.send(:expand_hash_conditions_for_aggregates, opts)
|
226
|
+
PredicateBuilder.new(table.engine).build_from_hash(attributes, table)
|
227
|
+
else
|
228
|
+
[opts]
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def build_joins(relation, joins)
|
233
|
+
association_joins = []
|
234
|
+
|
235
|
+
joins = @joins_values.map {|j| j.respond_to?(:strip) ? j.strip : j}.uniq
|
236
|
+
|
237
|
+
joins.each do |join|
|
238
|
+
association_joins << join if [Hash, Array, Symbol].include?(join.class) && !array_of_strings?(join)
|
239
|
+
end
|
240
|
+
|
241
|
+
stashed_association_joins = joins.grep(ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation)
|
242
|
+
|
243
|
+
non_association_joins = (joins - association_joins - stashed_association_joins)
|
244
|
+
custom_joins = custom_join_sql(*non_association_joins)
|
245
|
+
|
246
|
+
join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, custom_joins)
|
247
|
+
|
248
|
+
join_dependency.graft(*stashed_association_joins)
|
249
|
+
|
250
|
+
@implicit_readonly = true unless association_joins.empty? && stashed_association_joins.empty?
|
251
|
+
|
252
|
+
to_join = []
|
253
|
+
|
254
|
+
join_dependency.join_associations.each do |association|
|
255
|
+
if (association_relation = association.relation).is_a?(Array)
|
256
|
+
to_join << [association_relation.first, association.join_type, association.association_join.first]
|
257
|
+
to_join << [association_relation.last, association.join_type, association.association_join.last]
|
258
|
+
else
|
259
|
+
to_join << [association_relation, association.join_type, association.association_join]
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
to_join.uniq.each do |left, join_type, right|
|
264
|
+
relation = relation.join(left, join_type).on(*right)
|
265
|
+
end
|
266
|
+
|
267
|
+
relation.join(custom_joins)
|
268
|
+
end
|
269
|
+
|
270
|
+
def build_select(arel, selects)
|
271
|
+
unless selects.empty?
|
272
|
+
@implicit_readonly = false
|
273
|
+
arel.project(*selects)
|
274
|
+
else
|
275
|
+
arel.project(Arel::SqlLiteral.new(@klass.quoted_table_name + '.*'))
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
def apply_modules(modules)
|
280
|
+
unless modules.empty?
|
281
|
+
@extensions += modules
|
282
|
+
modules.each {|extension| extend(extension) }
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
def reverse_sql_order(order_query)
|
287
|
+
order_query.to_s.split(/,/).each { |s|
|
288
|
+
if s.match(/\s(asc|ASC)$/)
|
289
|
+
s.gsub!(/\s(asc|ASC)$/, ' DESC')
|
290
|
+
elsif s.match(/\s(desc|DESC)$/)
|
291
|
+
s.gsub!(/\s(desc|DESC)$/, ' ASC')
|
292
|
+
else
|
293
|
+
s.concat(' DESC')
|
294
|
+
end
|
295
|
+
}.join(',')
|
296
|
+
end
|
297
|
+
|
298
|
+
def array_of_strings?(o)
|
299
|
+
o.is_a?(Array) && o.all?{|obj| obj.is_a?(String)}
|
300
|
+
end
|
301
|
+
|
302
|
+
end
|
303
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'active_support/core_ext/object/blank'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module SpawnMethods
|
5
|
+
def merge(r)
|
6
|
+
merged_relation = clone
|
7
|
+
return merged_relation unless r
|
8
|
+
return to_a & r if r.is_a?(Array)
|
9
|
+
|
10
|
+
Relation::ASSOCIATION_METHODS.each do |method|
|
11
|
+
value = r.send(:"#{method}_values")
|
12
|
+
|
13
|
+
unless value.empty?
|
14
|
+
if method == :includes
|
15
|
+
merged_relation = merged_relation.includes(value)
|
16
|
+
else
|
17
|
+
merged_relation.send(:"#{method}_values=", value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
(Relation::MULTI_VALUE_METHODS - [:joins, :where, :order]).each do |method|
|
23
|
+
value = r.send(:"#{method}_values")
|
24
|
+
merged_relation.send(:"#{method}_values=", merged_relation.send(:"#{method}_values") + value) if value.present?
|
25
|
+
end
|
26
|
+
|
27
|
+
order_value = r.order_values
|
28
|
+
if order_value.present?
|
29
|
+
if r.reorder_flag
|
30
|
+
merged_relation.order_values = order_value
|
31
|
+
else
|
32
|
+
merged_relation.order_values = merged_relation.order_values + order_value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
merged_relation = merged_relation.joins(r.joins_values)
|
37
|
+
|
38
|
+
merged_wheres = @where_values + r.where_values
|
39
|
+
|
40
|
+
unless @where_values.empty?
|
41
|
+
# Remove duplicates, last one wins.
|
42
|
+
seen = Hash.new { |h,table| h[table] = {} }
|
43
|
+
merged_wheres = merged_wheres.reverse.reject { |w|
|
44
|
+
nuke = false
|
45
|
+
if w.respond_to?(:operator) && w.operator == :==
|
46
|
+
name = w.left.name
|
47
|
+
table = w.left.relation.name
|
48
|
+
nuke = seen[table][name]
|
49
|
+
seen[table][name] = true
|
50
|
+
end
|
51
|
+
nuke
|
52
|
+
}.reverse
|
53
|
+
end
|
54
|
+
|
55
|
+
merged_relation.where_values = merged_wheres
|
56
|
+
|
57
|
+
Relation::SINGLE_VALUE_METHODS.reject {|m| m == :lock}.each do |method|
|
58
|
+
value = r.send(:"#{method}_value")
|
59
|
+
merged_relation.send(:"#{method}_value=", value) unless value.nil?
|
60
|
+
end
|
61
|
+
|
62
|
+
merged_relation.lock_value = r.lock_value unless merged_relation.lock_value
|
63
|
+
|
64
|
+
# Apply scope extension modules
|
65
|
+
merged_relation.send :apply_modules, r.extensions
|
66
|
+
|
67
|
+
merged_relation
|
68
|
+
end
|
69
|
+
|
70
|
+
def &(r)
|
71
|
+
ActiveSupport::Deprecation.warn "Using & to merge relations has been deprecated and will be removed in Rails 3.1. Please use the relation's merge method, instead"
|
72
|
+
merge(r)
|
73
|
+
end
|
74
|
+
|
75
|
+
def except(*skips)
|
76
|
+
result = self.class.new(@klass, table)
|
77
|
+
|
78
|
+
((Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS) - skips).each do |method|
|
79
|
+
result.send(:"#{method}_values=", send(:"#{method}_values"))
|
80
|
+
end
|
81
|
+
|
82
|
+
(Relation::SINGLE_VALUE_METHODS - skips).each do |method|
|
83
|
+
result.send(:"#{method}_value=", send(:"#{method}_value"))
|
84
|
+
end
|
85
|
+
|
86
|
+
# Apply scope extension modules
|
87
|
+
result.send(:apply_modules, extensions)
|
88
|
+
|
89
|
+
result
|
90
|
+
end
|
91
|
+
|
92
|
+
def only(*onlies)
|
93
|
+
result = self.class.new(@klass, table)
|
94
|
+
|
95
|
+
((Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS) & onlies).each do |method|
|
96
|
+
result.send(:"#{method}_values=", send(:"#{method}_values"))
|
97
|
+
end
|
98
|
+
|
99
|
+
(Relation::SINGLE_VALUE_METHODS & onlies).each do |method|
|
100
|
+
result.send(:"#{method}_value=", send(:"#{method}_value"))
|
101
|
+
end
|
102
|
+
|
103
|
+
# Apply scope extension modules
|
104
|
+
result.send(:apply_modules, extensions)
|
105
|
+
|
106
|
+
result
|
107
|
+
end
|
108
|
+
|
109
|
+
VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :extend,
|
110
|
+
:order, :select, :readonly, :group, :having, :from, :lock ]
|
111
|
+
|
112
|
+
def apply_finder_options(options)
|
113
|
+
relation = clone
|
114
|
+
return relation unless options
|
115
|
+
|
116
|
+
options.assert_valid_keys(VALID_FIND_OPTIONS)
|
117
|
+
finders = options.dup
|
118
|
+
finders.delete_if { |key, value| value.nil? }
|
119
|
+
|
120
|
+
([:joins, :select, :group, :order, :having, :limit, :offset, :from, :lock, :readonly] & finders.keys).each do |finder|
|
121
|
+
relation = relation.send(finder, finders[finder])
|
122
|
+
end
|
123
|
+
|
124
|
+
relation = relation.where(finders[:conditions]) if options.has_key?(:conditions)
|
125
|
+
relation = relation.includes(finders[:include]) if options.has_key?(:include)
|
126
|
+
relation = relation.extending(finders[:extend]) if options.has_key?(:extend)
|
127
|
+
|
128
|
+
relation
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|