activerecord 1.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- data/CHANGELOG +5518 -76
- data/README.rdoc +222 -0
- data/examples/performance.rb +162 -0
- data/examples/simple.rb +14 -0
- data/lib/active_record/aggregations.rb +192 -80
- data/lib/active_record/association_preload.rb +403 -0
- data/lib/active_record/associations/association_collection.rb +545 -53
- data/lib/active_record/associations/association_proxy.rb +295 -0
- data/lib/active_record/associations/belongs_to_association.rb +91 -0
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +78 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +127 -36
- data/lib/active_record/associations/has_many_association.rb +108 -84
- data/lib/active_record/associations/has_many_through_association.rb +116 -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/associations.rb +2086 -368
- data/lib/active_record/attribute_methods/before_type_cast.rb +33 -0
- data/lib/active_record/attribute_methods/dirty.rb +95 -0
- data/lib/active_record/attribute_methods/primary_key.rb +50 -0
- data/lib/active_record/attribute_methods/query.rb +39 -0
- data/lib/active_record/attribute_methods/read.rb +116 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -0
- data/lib/active_record/attribute_methods/write.rb +37 -0
- data/lib/active_record/attribute_methods.rb +60 -0
- data/lib/active_record/autosave_association.rb +369 -0
- data/lib/active_record/base.rb +1603 -721
- data/lib/active_record/callbacks.rb +176 -225
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +365 -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 +329 -0
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +81 -0
- data/lib/active_record/connection_adapters/abstract/quoting.rb +72 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +739 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +543 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +165 -279
- data/lib/active_record/connection_adapters/mysql_adapter.rb +594 -82
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +988 -135
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +53 -0
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +365 -71
- data/lib/active_record/counter_cache.rb +115 -0
- data/lib/active_record/dynamic_finder_match.rb +53 -0
- data/lib/active_record/dynamic_scope_match.rb +32 -0
- data/lib/active_record/errors.rb +172 -0
- data/lib/active_record/fixtures.rb +941 -105
- 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 +417 -0
- data/lib/active_record/observer.rb +105 -36
- data/lib/active_record/persistence.rb +291 -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 +364 -87
- data/lib/active_record/relation/batches.rb +89 -0
- data/lib/active_record/relation/calculations.rb +286 -0
- data/lib/active_record/relation/finder_methods.rb +355 -0
- data/lib/active_record/relation/predicate_builder.rb +41 -0
- data/lib/active_record/relation/query_methods.rb +261 -0
- data/lib/active_record/relation/spawn_methods.rb +112 -0
- data/lib/active_record/relation.rb +393 -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 +329 -75
- data/lib/active_record/validations/associated.rb +48 -0
- data/lib/active_record/validations/uniqueness.rb +185 -0
- data/lib/active_record/validations.rb +58 -179
- data/lib/active_record/version.rb +9 -0
- data/lib/active_record.rb +100 -24
- 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
- data/lib/rails/generators/active_record.rb +27 -0
- metadata +216 -158
- data/README +0 -361
- data/RUNNING_UNIT_TESTS +0 -36
- data/dev-utils/eval_debugger.rb +0 -9
- data/examples/associations.rb +0 -87
- data/examples/shared_setup.rb +0 -15
- data/examples/validation.rb +0 -88
- data/install.rb +0 -60
- data/lib/active_record/deprecated_associations.rb +0 -70
- data/lib/active_record/support/class_attribute_accessors.rb +0 -43
- data/lib/active_record/support/class_inheritable_attributes.rb +0 -37
- data/lib/active_record/support/clean_logger.rb +0 -10
- data/lib/active_record/support/inflector.rb +0 -70
- data/lib/active_record/vendor/mysql.rb +0 -1117
- data/lib/active_record/vendor/simple.rb +0 -702
- data/lib/active_record/wrappers/yaml_wrapper.rb +0 -15
- data/lib/active_record/wrappings.rb +0 -59
- data/rakefile +0 -122
- data/test/abstract_unit.rb +0 -16
- data/test/aggregations_test.rb +0 -34
- data/test/all.sh +0 -8
- data/test/associations_test.rb +0 -477
- data/test/base_test.rb +0 -513
- data/test/class_inheritable_attributes_test.rb +0 -33
- data/test/connections/native_mysql/connection.rb +0 -24
- data/test/connections/native_postgresql/connection.rb +0 -24
- data/test/connections/native_sqlite/connection.rb +0 -24
- data/test/deprecated_associations_test.rb +0 -336
- data/test/finder_test.rb +0 -67
- data/test/fixtures/accounts/signals37 +0 -3
- data/test/fixtures/accounts/unknown +0 -2
- data/test/fixtures/auto_id.rb +0 -4
- data/test/fixtures/column_name.rb +0 -3
- data/test/fixtures/companies/first_client +0 -6
- data/test/fixtures/companies/first_firm +0 -4
- data/test/fixtures/companies/second_client +0 -6
- data/test/fixtures/company.rb +0 -37
- data/test/fixtures/company_in_module.rb +0 -33
- data/test/fixtures/course.rb +0 -3
- data/test/fixtures/courses/java +0 -2
- data/test/fixtures/courses/ruby +0 -2
- data/test/fixtures/customer.rb +0 -30
- data/test/fixtures/customers/david +0 -6
- data/test/fixtures/db_definitions/mysql.sql +0 -96
- data/test/fixtures/db_definitions/mysql2.sql +0 -4
- data/test/fixtures/db_definitions/postgresql.sql +0 -113
- data/test/fixtures/db_definitions/postgresql2.sql +0 -4
- data/test/fixtures/db_definitions/sqlite.sql +0 -85
- data/test/fixtures/db_definitions/sqlite2.sql +0 -4
- data/test/fixtures/default.rb +0 -2
- data/test/fixtures/developer.rb +0 -8
- data/test/fixtures/developers/david +0 -2
- data/test/fixtures/developers/jamis +0 -2
- data/test/fixtures/developers_projects/david_action_controller +0 -2
- data/test/fixtures/developers_projects/david_active_record +0 -2
- data/test/fixtures/developers_projects/jamis_active_record +0 -2
- data/test/fixtures/entrant.rb +0 -3
- data/test/fixtures/entrants/first +0 -3
- data/test/fixtures/entrants/second +0 -3
- data/test/fixtures/entrants/third +0 -3
- data/test/fixtures/fixture_database.sqlite +0 -0
- data/test/fixtures/fixture_database_2.sqlite +0 -0
- data/test/fixtures/movie.rb +0 -5
- data/test/fixtures/movies/first +0 -2
- data/test/fixtures/movies/second +0 -2
- data/test/fixtures/project.rb +0 -3
- data/test/fixtures/projects/action_controller +0 -2
- data/test/fixtures/projects/active_record +0 -2
- data/test/fixtures/reply.rb +0 -21
- data/test/fixtures/subscriber.rb +0 -5
- data/test/fixtures/subscribers/first +0 -2
- data/test/fixtures/subscribers/second +0 -2
- data/test/fixtures/topic.rb +0 -20
- data/test/fixtures/topics/first +0 -9
- data/test/fixtures/topics/second +0 -8
- data/test/fixtures_test.rb +0 -20
- data/test/inflector_test.rb +0 -104
- data/test/inheritance_test.rb +0 -125
- data/test/lifecycle_test.rb +0 -110
- data/test/modules_test.rb +0 -21
- data/test/multiple_db_test.rb +0 -46
- data/test/pk_test.rb +0 -57
- data/test/reflection_test.rb +0 -78
- data/test/thread_safety_test.rb +0 -33
- data/test/transactions_test.rb +0 -83
- data/test/unconnected_test.rb +0 -24
- data/test/validations_test.rb +0 -126
@@ -0,0 +1,261 @@
|
|
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, :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
|
+
clone.tap {|r| r.includes_values = (r.includes_values + args).flatten.uniq if args.present? }
|
15
|
+
end
|
16
|
+
|
17
|
+
def eager_load(*args)
|
18
|
+
clone.tap {|r| r.eager_load_values += args if args.present? }
|
19
|
+
end
|
20
|
+
|
21
|
+
def preload(*args)
|
22
|
+
clone.tap {|r| r.preload_values += args if args.present? }
|
23
|
+
end
|
24
|
+
|
25
|
+
def select(*args)
|
26
|
+
if block_given?
|
27
|
+
to_a.select {|*block_args| yield(*block_args) }
|
28
|
+
else
|
29
|
+
clone.tap {|r| r.select_values += args if args.present? }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def group(*args)
|
34
|
+
clone.tap {|r| r.group_values += args.flatten if args.present? }
|
35
|
+
end
|
36
|
+
|
37
|
+
def order(*args)
|
38
|
+
clone.tap {|r| r.order_values += args if args.present? }
|
39
|
+
end
|
40
|
+
|
41
|
+
def reorder(*args)
|
42
|
+
clone.tap {|r| r.order_values = args if args.present? }
|
43
|
+
end
|
44
|
+
|
45
|
+
def joins(*args)
|
46
|
+
args.flatten!
|
47
|
+
clone.tap {|r| r.joins_values += args if args.present? }
|
48
|
+
end
|
49
|
+
|
50
|
+
def where(opts, *rest)
|
51
|
+
value = build_where(opts, rest)
|
52
|
+
copy = clone
|
53
|
+
copy.where_values += Array.wrap(value) if value
|
54
|
+
copy
|
55
|
+
end
|
56
|
+
|
57
|
+
def having(*args)
|
58
|
+
value = build_where(*args)
|
59
|
+
clone.tap {|r| r.having_values += Array.wrap(value) if value.present? }
|
60
|
+
end
|
61
|
+
|
62
|
+
def limit(value = true)
|
63
|
+
copy = clone
|
64
|
+
copy.limit_value = value
|
65
|
+
copy
|
66
|
+
end
|
67
|
+
|
68
|
+
def offset(value = true)
|
69
|
+
clone.tap {|r| r.offset_value = value }
|
70
|
+
end
|
71
|
+
|
72
|
+
def lock(locks = true)
|
73
|
+
case locks
|
74
|
+
when String, TrueClass, NilClass
|
75
|
+
clone.tap {|r| r.lock_value = locks || true }
|
76
|
+
else
|
77
|
+
clone.tap {|r| r.lock_value = false }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def readonly(value = true)
|
82
|
+
clone.tap {|r| r.readonly_value = value }
|
83
|
+
end
|
84
|
+
|
85
|
+
def create_with(value = true)
|
86
|
+
clone.tap {|r| r.create_with_value = value }
|
87
|
+
end
|
88
|
+
|
89
|
+
def from(value = true)
|
90
|
+
clone.tap {|r| r.from_value = value }
|
91
|
+
end
|
92
|
+
|
93
|
+
def extending(*modules, &block)
|
94
|
+
modules << Module.new(&block) if block_given?
|
95
|
+
clone.tap {|r| r.send(:apply_modules, *modules) }
|
96
|
+
end
|
97
|
+
|
98
|
+
def reverse_order
|
99
|
+
order_clause = arel.order_clauses.join(', ')
|
100
|
+
relation = except(:order)
|
101
|
+
|
102
|
+
order = order_clause.blank? ?
|
103
|
+
"#{@klass.table_name}.#{@klass.primary_key} DESC" :
|
104
|
+
reverse_sql_order(order_clause)
|
105
|
+
|
106
|
+
relation.order Arel::SqlLiteral.new order
|
107
|
+
end
|
108
|
+
|
109
|
+
def arel
|
110
|
+
@arel ||= build_arel
|
111
|
+
end
|
112
|
+
|
113
|
+
def custom_join_sql(*joins)
|
114
|
+
arel = table
|
115
|
+
joins.each do |join|
|
116
|
+
next if join.blank?
|
117
|
+
|
118
|
+
@implicit_readonly = true
|
119
|
+
|
120
|
+
case join
|
121
|
+
when Hash, Array, Symbol
|
122
|
+
if array_of_strings?(join)
|
123
|
+
join_string = join.join(' ')
|
124
|
+
arel = arel.join(Arel::SqlLiteral.new(join_string))
|
125
|
+
end
|
126
|
+
when String
|
127
|
+
arel = arel.join(Arel::SqlLiteral.new(join))
|
128
|
+
else
|
129
|
+
arel = arel.join(join)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
arel.joins(arel)
|
133
|
+
end
|
134
|
+
|
135
|
+
def build_arel
|
136
|
+
arel = table
|
137
|
+
|
138
|
+
arel = build_joins(arel, @joins_values) unless @joins_values.empty?
|
139
|
+
|
140
|
+
(@where_values - ['']).uniq.each do |where|
|
141
|
+
case where
|
142
|
+
when Arel::SqlLiteral
|
143
|
+
arel = arel.where(where)
|
144
|
+
else
|
145
|
+
sql = where.is_a?(String) ? where : where.to_sql
|
146
|
+
arel = arel.where(Arel::SqlLiteral.new("(#{sql})"))
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
arel = arel.having(*@having_values.uniq.select{|h| h.present?}) unless @having_values.empty?
|
151
|
+
|
152
|
+
arel = arel.take(@limit_value) if @limit_value
|
153
|
+
arel = arel.skip(@offset_value) if @offset_value
|
154
|
+
|
155
|
+
arel = arel.group(*@group_values.uniq.select{|g| g.present?}) unless @group_values.empty?
|
156
|
+
|
157
|
+
arel = arel.order(*@order_values.uniq.select{|o| o.present?}) unless @order_values.empty?
|
158
|
+
|
159
|
+
arel = build_select(arel, @select_values.uniq)
|
160
|
+
|
161
|
+
arel = arel.from(@from_value) if @from_value
|
162
|
+
arel = arel.lock(@lock_value) if @lock_value
|
163
|
+
|
164
|
+
arel
|
165
|
+
end
|
166
|
+
|
167
|
+
def build_where(opts, other = [])
|
168
|
+
case opts
|
169
|
+
when String, Array
|
170
|
+
@klass.send(:sanitize_sql, other.empty? ? opts : ([opts] + other))
|
171
|
+
when Hash
|
172
|
+
attributes = @klass.send(:expand_hash_conditions_for_aggregates, opts)
|
173
|
+
PredicateBuilder.new(table.engine).build_from_hash(attributes, table)
|
174
|
+
else
|
175
|
+
opts
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
|
181
|
+
def build_joins(relation, joins)
|
182
|
+
joined_associations = []
|
183
|
+
association_joins = []
|
184
|
+
|
185
|
+
joins = @joins_values.map {|j| j.respond_to?(:strip) ? j.strip : j}.uniq
|
186
|
+
|
187
|
+
joins.each do |join|
|
188
|
+
association_joins << join if [Hash, Array, Symbol].include?(join.class) && !array_of_strings?(join)
|
189
|
+
end
|
190
|
+
|
191
|
+
stashed_association_joins = joins.grep(ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation)
|
192
|
+
|
193
|
+
non_association_joins = (joins - association_joins - stashed_association_joins)
|
194
|
+
custom_joins = custom_join_sql(*non_association_joins)
|
195
|
+
|
196
|
+
join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, custom_joins)
|
197
|
+
|
198
|
+
join_dependency.graft(*stashed_association_joins)
|
199
|
+
|
200
|
+
@implicit_readonly = true unless association_joins.empty? && stashed_association_joins.empty?
|
201
|
+
|
202
|
+
to_join = []
|
203
|
+
|
204
|
+
join_dependency.join_associations.each do |association|
|
205
|
+
if (association_relation = association.relation).is_a?(Array)
|
206
|
+
to_join << [association_relation.first, association.join_class, association.association_join.first]
|
207
|
+
to_join << [association_relation.last, association.join_class, association.association_join.last]
|
208
|
+
else
|
209
|
+
to_join << [association_relation, association.join_class, association.association_join]
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
to_join.each do |tj|
|
214
|
+
unless joined_associations.detect {|ja| ja[0] == tj[0] && ja[1] == tj[1] && ja[2] == tj[2] }
|
215
|
+
joined_associations << tj
|
216
|
+
relation = relation.join(tj[0], tj[1]).on(*tj[2])
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
relation.join(custom_joins)
|
221
|
+
end
|
222
|
+
|
223
|
+
def build_select(arel, selects)
|
224
|
+
unless selects.empty?
|
225
|
+
@implicit_readonly = false
|
226
|
+
# TODO: fix this ugly hack, we should refactor the callers to get an ARel compatible array.
|
227
|
+
# Before this change we were passing to ARel the last element only, and ARel is capable of handling an array
|
228
|
+
if selects.all? {|s| s.is_a?(String) || !s.is_a?(Arel::Expression) } && !(selects.last =~ /^COUNT\(/)
|
229
|
+
arel.project(*selects)
|
230
|
+
else
|
231
|
+
arel.project(selects.last)
|
232
|
+
end
|
233
|
+
else
|
234
|
+
arel.project(Arel::SqlLiteral.new(@klass.quoted_table_name + '.*'))
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def apply_modules(modules)
|
239
|
+
values = Array.wrap(modules)
|
240
|
+
@extensions += values if values.present?
|
241
|
+
values.each {|extension| extend(extension) }
|
242
|
+
end
|
243
|
+
|
244
|
+
def reverse_sql_order(order_query)
|
245
|
+
order_query.to_s.split(/,/).each { |s|
|
246
|
+
if s.match(/\s(asc|ASC)$/)
|
247
|
+
s.gsub!(/\s(asc|ASC)$/, ' DESC')
|
248
|
+
elsif s.match(/\s(desc|DESC)$/)
|
249
|
+
s.gsub!(/\s(desc|DESC)$/, ' ASC')
|
250
|
+
else
|
251
|
+
s.concat(' DESC')
|
252
|
+
end
|
253
|
+
}.join(',')
|
254
|
+
end
|
255
|
+
|
256
|
+
def array_of_strings?(o)
|
257
|
+
o.is_a?(Array) && o.all?{|obj| obj.is_a?(String)}
|
258
|
+
end
|
259
|
+
|
260
|
+
end
|
261
|
+
end
|
@@ -0,0 +1,112 @@
|
|
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
|
+
|
9
|
+
((Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS) - [:joins, :where]).each do |method|
|
10
|
+
value = r.send(:"#{method}_values")
|
11
|
+
unless value.empty?
|
12
|
+
if method == :includes
|
13
|
+
merged_relation = merged_relation.includes(value)
|
14
|
+
else
|
15
|
+
merged_relation.send(:"#{method}_values=", value)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
merged_relation = merged_relation.joins(r.joins_values)
|
21
|
+
|
22
|
+
merged_wheres = @where_values
|
23
|
+
|
24
|
+
r.where_values.each do |w|
|
25
|
+
if w.respond_to?(:operator) && w.operator == :==
|
26
|
+
merged_wheres = merged_wheres.reject { |p|
|
27
|
+
p.respond_to?(:operator) && p.operator == :== && p.operand1.name == w.operand1.name
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
merged_wheres += [w]
|
32
|
+
end
|
33
|
+
|
34
|
+
merged_relation.where_values = merged_wheres
|
35
|
+
|
36
|
+
Relation::SINGLE_VALUE_METHODS.reject {|m| m == :lock}.each do |method|
|
37
|
+
unless (value = r.send(:"#{method}_value")).nil?
|
38
|
+
merged_relation.send(:"#{method}_value=", value)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
merged_relation.lock_value = r.lock_value unless merged_relation.lock_value
|
43
|
+
|
44
|
+
# Apply scope extension modules
|
45
|
+
merged_relation.send :apply_modules, r.extensions
|
46
|
+
|
47
|
+
merged_relation
|
48
|
+
end
|
49
|
+
|
50
|
+
alias :& :merge
|
51
|
+
|
52
|
+
def except(*skips)
|
53
|
+
result = self.class.new(@klass, table)
|
54
|
+
|
55
|
+
(Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS).each do |method|
|
56
|
+
result.send(:"#{method}_values=", send(:"#{method}_values")) unless skips.include?(method)
|
57
|
+
end
|
58
|
+
|
59
|
+
Relation::SINGLE_VALUE_METHODS.each do |method|
|
60
|
+
result.send(:"#{method}_value=", send(:"#{method}_value")) unless skips.include?(method)
|
61
|
+
end
|
62
|
+
|
63
|
+
result
|
64
|
+
end
|
65
|
+
|
66
|
+
def only(*onlies)
|
67
|
+
result = self.class.new(@klass, table)
|
68
|
+
|
69
|
+
onlies.each do |only|
|
70
|
+
if (Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS).include?(only)
|
71
|
+
result.send(:"#{only}_values=", send(:"#{only}_values"))
|
72
|
+
elsif Relation::SINGLE_VALUE_METHODS.include?(only)
|
73
|
+
result.send(:"#{only}_value=", send(:"#{only}_value"))
|
74
|
+
else
|
75
|
+
raise "Invalid argument : #{only}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
result
|
80
|
+
end
|
81
|
+
|
82
|
+
VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :extend,
|
83
|
+
:order, :select, :readonly, :group, :having, :from, :lock ]
|
84
|
+
|
85
|
+
def apply_finder_options(options)
|
86
|
+
relation = clone
|
87
|
+
return relation unless options
|
88
|
+
|
89
|
+
options.assert_valid_keys(VALID_FIND_OPTIONS)
|
90
|
+
|
91
|
+
[:joins, :select, :group, :having, :limit, :offset, :from, :lock].each do |finder|
|
92
|
+
if value = options[finder]
|
93
|
+
relation = relation.send(finder, value)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
relation = relation.readonly(options[:readonly]) if options.key? :readonly
|
98
|
+
|
99
|
+
# Give precedence to newly-applied orders and groups to play nicely with with_scope
|
100
|
+
[:group, :order].each do |finder|
|
101
|
+
relation.send("#{finder}_values=", Array.wrap(options[finder]) + relation.send("#{finder}_values")) if options.has_key?(finder)
|
102
|
+
end
|
103
|
+
|
104
|
+
relation = relation.where(options[:conditions]) if options.has_key?(:conditions)
|
105
|
+
relation = relation.includes(options[:include]) if options.has_key?(:include)
|
106
|
+
relation = relation.extending(options[:extend]) if options.has_key?(:extend)
|
107
|
+
|
108
|
+
relation
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|