activerecord 4.2.11.3 → 5.0.0.beta1
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +1029 -1349
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -7
- data/examples/performance.rb +2 -2
- data/lib/active_record.rb +7 -3
- data/lib/active_record/aggregations.rb +35 -25
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations.rb +305 -204
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +10 -8
- data/lib/active_record/associations/association_scope.rb +73 -102
- data/lib/active_record/associations/belongs_to_association.rb +20 -32
- data/lib/active_record/associations/builder/association.rb +28 -34
- data/lib/active_record/associations/builder/belongs_to.rb +41 -18
- data/lib/active_record/associations/builder/collection_association.rb +8 -24
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +11 -11
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +10 -5
- data/lib/active_record/associations/builder/singular_association.rb +2 -9
- data/lib/active_record/associations/collection_association.rb +40 -43
- data/lib/active_record/associations/collection_proxy.rb +55 -29
- data/lib/active_record/associations/foreign_association.rb +1 -1
- data/lib/active_record/associations/has_many_association.rb +20 -71
- data/lib/active_record/associations/has_many_through_association.rb +8 -52
- data/lib/active_record/associations/has_one_association.rb +12 -5
- data/lib/active_record/associations/join_dependency.rb +28 -18
- data/lib/active_record/associations/join_dependency/join_association.rb +13 -12
- data/lib/active_record/associations/preloader.rb +13 -4
- data/lib/active_record/associations/preloader/association.rb +45 -51
- data/lib/active_record/associations/preloader/collection_association.rb +0 -6
- data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
- data/lib/active_record/associations/preloader/has_one.rb +0 -8
- data/lib/active_record/associations/preloader/through_association.rb +5 -4
- data/lib/active_record/associations/singular_association.rb +6 -0
- data/lib/active_record/associations/through_association.rb +11 -3
- data/lib/active_record/attribute.rb +61 -17
- data/lib/active_record/attribute/user_provided_default.rb +23 -0
- data/lib/active_record/attribute_assignment.rb +27 -140
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods.rb +79 -26
- data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
- data/lib/active_record/attribute_methods/dirty.rb +46 -86
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +26 -42
- data/lib/active_record/attribute_methods/serialization.rb +13 -16
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +42 -9
- data/lib/active_record/attribute_methods/write.rb +13 -24
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set.rb +30 -3
- data/lib/active_record/attribute_set/builder.rb +6 -4
- data/lib/active_record/attributes.rb +194 -81
- data/lib/active_record/autosave_association.rb +33 -15
- data/lib/active_record/base.rb +30 -18
- data/lib/active_record/callbacks.rb +36 -40
- data/lib/active_record/coders/yaml_column.rb +20 -8
- data/lib/active_record/collection_cache_key.rb +31 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +431 -122
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +40 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -8
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +46 -38
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +229 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +52 -13
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +275 -115
- data/lib/active_record/connection_adapters/abstract/transaction.rb +32 -33
- data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -32
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +384 -221
- data/lib/active_record/connection_adapters/column.rb +27 -41
- data/lib/active_record/connection_adapters/connection_specification.rb +2 -21
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +57 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +69 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +59 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +22 -101
- data/lib/active_record/connection_adapters/postgresql/column.rb +6 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +23 -57
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +23 -16
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -11
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +54 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +174 -128
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +184 -112
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +134 -110
- data/lib/active_record/connection_adapters/statement_pool.rb +28 -11
- data/lib/active_record/connection_handling.rb +5 -5
- data/lib/active_record/core.rb +72 -104
- data/lib/active_record/counter_cache.rb +9 -20
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +110 -76
- data/lib/active_record/errors.rb +72 -47
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +19 -4
- data/lib/active_record/fixtures.rb +76 -40
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +27 -40
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/legacy_yaml_adapter.rb +18 -2
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +10 -14
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +40 -22
- data/lib/active_record/migration.rb +304 -133
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +90 -0
- data/lib/active_record/model_schema.rb +92 -40
- data/lib/active_record/nested_attributes.rb +45 -34
- data/lib/active_record/null_relation.rb +15 -7
- data/lib/active_record/persistence.rb +112 -72
- data/lib/active_record/querying.rb +6 -5
- data/lib/active_record/railtie.rb +20 -13
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +47 -38
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +182 -57
- data/lib/active_record/relation.rb +152 -100
- data/lib/active_record/relation/batches.rb +133 -33
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/calculations.rb +80 -101
- data/lib/active_record/relation/delegation.rb +6 -19
- data/lib/active_record/relation/finder_methods.rb +58 -46
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +13 -42
- data/lib/active_record/relation/predicate_builder.rb +99 -105
- data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +78 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +17 -0
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +274 -238
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +3 -6
- data/lib/active_record/relation/where_clause.rb +173 -0
- data/lib/active_record/relation/where_clause_factory.rb +37 -0
- data/lib/active_record/result.rb +4 -3
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +94 -65
- data/lib/active_record/schema.rb +23 -22
- data/lib/active_record/schema_dumper.rb +33 -22
- data/lib/active_record/schema_migration.rb +10 -4
- data/lib/active_record/scoping.rb +17 -6
- data/lib/active_record/scoping/default.rb +19 -6
- data/lib/active_record/scoping/named.rb +39 -28
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +2 -4
- data/lib/active_record/statement_cache.rb +15 -13
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +54 -0
- data/lib/active_record/table_metadata.rb +64 -0
- data/lib/active_record/tasks/database_tasks.rb +30 -40
- data/lib/active_record/tasks/mysql_database_tasks.rb +7 -15
- data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
- data/lib/active_record/timestamp.rb +16 -9
- data/lib/active_record/touch_later.rb +58 -0
- data/lib/active_record/transactions.rb +138 -56
- data/lib/active_record/type.rb +66 -17
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +2 -45
- data/lib/active_record/type/date_time.rb +2 -49
- data/lib/active_record/type/internal/abstract_json.rb +33 -0
- data/lib/active_record/type/internal/timezone.rb +15 -0
- data/lib/active_record/type/serialized.rb +9 -14
- data/lib/active_record/type/time.rb +3 -21
- data/lib/active_record/type/type_map.rb +4 -4
- data/lib/active_record/type_caster.rb +7 -0
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record/validations/absence.rb +24 -0
- data/lib/active_record/validations/associated.rb +10 -3
- data/lib/active_record/validations/length.rb +36 -0
- data/lib/active_record/validations/presence.rb +12 -12
- data/lib/active_record/validations/uniqueness.rb +24 -21
- data/lib/rails/generators/active_record/migration.rb +7 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
- data/lib/rails/generators/active_record/migration/templates/migration.rb +4 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +21 -15
- data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
- metadata +50 -35
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -64
- data/lib/active_record/type/decimal_without_scale.rb +0 -11
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/text.rb +0 -11
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/unsigned_integer.rb +0 -15
- data/lib/active_record/type/value.rb +0 -110
@@ -1,15 +1,14 @@
|
|
1
1
|
require 'set'
|
2
2
|
require 'active_support/concern'
|
3
|
-
require 'active_support/deprecation'
|
4
3
|
|
5
4
|
module ActiveRecord
|
6
5
|
module Delegation # :nodoc:
|
7
|
-
module DelegateCache
|
8
|
-
def relation_delegate_class(klass)
|
6
|
+
module DelegateCache # :nodoc:
|
7
|
+
def relation_delegate_class(klass)
|
9
8
|
@relation_delegate_cache[klass]
|
10
9
|
end
|
11
10
|
|
12
|
-
def initialize_relation_delegate_cache
|
11
|
+
def initialize_relation_delegate_cache
|
13
12
|
@relation_delegate_cache = cache = {}
|
14
13
|
[
|
15
14
|
ActiveRecord::Relation,
|
@@ -19,7 +18,7 @@ module ActiveRecord
|
|
19
18
|
delegate = Class.new(klass) {
|
20
19
|
include ClassSpecificRelation
|
21
20
|
}
|
22
|
-
const_set klass.name.gsub('::', '_'), delegate
|
21
|
+
const_set klass.name.gsub('::'.freeze, '_'.freeze), delegate
|
23
22
|
cache[klass] = delegate
|
24
23
|
end
|
25
24
|
end
|
@@ -37,13 +36,8 @@ module ActiveRecord
|
|
37
36
|
# may vary depending on the klass of a relation, so we create a subclass of Relation
|
38
37
|
# for each different klass, and the delegations are compiled into that subclass only.
|
39
38
|
|
40
|
-
|
41
|
-
:
|
42
|
-
:shuffle!, :slice!, :sort!, :sort_by!, :delete_if,
|
43
|
-
:keep_if, :pop, :shift, :delete_at, :select!
|
44
|
-
].to_set # :nodoc:
|
45
|
-
|
46
|
-
delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to_ary, :join, to: :to_a
|
39
|
+
delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to_ary, :join,
|
40
|
+
:[], :&, :|, :+, :-, :sample, :shuffle, :reverse, :compact, to: :to_a
|
47
41
|
|
48
42
|
delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key,
|
49
43
|
:connection, :columns_hash, :to => :klass
|
@@ -115,21 +109,14 @@ module ActiveRecord
|
|
115
109
|
|
116
110
|
def respond_to?(method, include_private = false)
|
117
111
|
super || @klass.respond_to?(method, include_private) ||
|
118
|
-
array_delegable?(method) ||
|
119
112
|
arel.respond_to?(method, include_private)
|
120
113
|
end
|
121
114
|
|
122
115
|
protected
|
123
116
|
|
124
|
-
def array_delegable?(method)
|
125
|
-
Array.method_defined?(method) && BLACKLISTED_ARRAY_METHODS.exclude?(method)
|
126
|
-
end
|
127
|
-
|
128
117
|
def method_missing(method, *args, &block)
|
129
118
|
if @klass.respond_to?(method)
|
130
119
|
scoping { @klass.public_send(method, *args, &block) }
|
131
|
-
elsif array_delegable?(method)
|
132
|
-
to_a.public_send(method, *args, &block)
|
133
120
|
elsif arel.respond_to?(method)
|
134
121
|
arel.public_send(method, *args, &block)
|
135
122
|
else
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'active_support/deprecation'
|
2
1
|
require 'active_support/core_ext/string/filters'
|
3
2
|
|
4
3
|
module ActiveRecord
|
@@ -6,7 +5,7 @@ module ActiveRecord
|
|
6
5
|
ONE_AS_ONE = '1 AS one'
|
7
6
|
|
8
7
|
# Find by id - This can either be a specific id (1), a list of ids (1, 5, 6), or an array of ids ([5, 6, 10]).
|
9
|
-
# If
|
8
|
+
# If one or more records can not be found for the requested ids, then RecordNotFound will be raised. If the primary key
|
10
9
|
# is an integer, find by id coerces its arguments using +to_i+.
|
11
10
|
#
|
12
11
|
# Person.find(1) # returns the object for ID = 1
|
@@ -17,10 +16,8 @@ module ActiveRecord
|
|
17
16
|
# Person.find([1]) # returns an array for the object with ID = 1
|
18
17
|
# Person.where("administrator = 1").order("created_on DESC").find(1)
|
19
18
|
#
|
20
|
-
# <tt>ActiveRecord::RecordNotFound</tt> will be raised if one or more ids are not found.
|
21
|
-
#
|
22
19
|
# NOTE: The returned records may not be in the same order as the ids you
|
23
|
-
# provide since database rows are unordered. You'd need to provide an explicit
|
20
|
+
# provide since database rows are unordered. You'd need to provide an explicit QueryMethods#order
|
24
21
|
# option if you want the results are sorted.
|
25
22
|
#
|
26
23
|
# ==== Find with lock
|
@@ -37,7 +34,7 @@ module ActiveRecord
|
|
37
34
|
# person.save!
|
38
35
|
# end
|
39
36
|
#
|
40
|
-
# ==== Variations of
|
37
|
+
# ==== Variations of #find
|
41
38
|
#
|
42
39
|
# Person.where(name: 'Spartacus', rating: 4)
|
43
40
|
# # returns a chainable list (which can be empty).
|
@@ -49,9 +46,9 @@ module ActiveRecord
|
|
49
46
|
# # returns the first item or returns a new instance (requires you call .save to persist against the database).
|
50
47
|
#
|
51
48
|
# Person.where(name: 'Spartacus', rating: 4).first_or_create
|
52
|
-
# # returns the first item or creates it and returns it
|
49
|
+
# # returns the first item or creates it and returns it.
|
53
50
|
#
|
54
|
-
# ==== Alternatives for
|
51
|
+
# ==== Alternatives for #find
|
55
52
|
#
|
56
53
|
# Person.where(name: 'Spartacus', rating: 4).exists?(conditions = :none)
|
57
54
|
# # returns a boolean indicating if any record with the given conditions exist.
|
@@ -60,16 +57,13 @@ module ActiveRecord
|
|
60
57
|
# # returns a chainable list of instances with only the mentioned fields.
|
61
58
|
#
|
62
59
|
# Person.where(name: 'Spartacus', rating: 4).ids
|
63
|
-
# # returns an Array of ids
|
60
|
+
# # returns an Array of ids.
|
64
61
|
#
|
65
62
|
# Person.where(name: 'Spartacus', rating: 4).pluck(:field1, :field2)
|
66
|
-
# # returns an Array of the required fields
|
63
|
+
# # returns an Array of the required fields.
|
67
64
|
def find(*args)
|
68
|
-
if block_given?
|
69
|
-
|
70
|
-
else
|
71
|
-
find_with_ids(*args)
|
72
|
-
end
|
65
|
+
return super if block_given?
|
66
|
+
find_with_ids(*args)
|
73
67
|
end
|
74
68
|
|
75
69
|
# Finds the first record matching the specified conditions. There
|
@@ -80,18 +74,19 @@ module ActiveRecord
|
|
80
74
|
#
|
81
75
|
# Post.find_by name: 'Spartacus', rating: 4
|
82
76
|
# Post.find_by "published_at < ?", 2.weeks.ago
|
83
|
-
def find_by(*args)
|
84
|
-
where(*args).take
|
77
|
+
def find_by(arg, *args)
|
78
|
+
where(arg, *args).take
|
85
79
|
rescue RangeError
|
86
80
|
nil
|
87
81
|
end
|
88
82
|
|
89
|
-
# Like
|
90
|
-
# an
|
91
|
-
def find_by!(*args)
|
92
|
-
where(*args).take!
|
83
|
+
# Like #find_by, except that if no record is found, raises
|
84
|
+
# an ActiveRecord::RecordNotFound error.
|
85
|
+
def find_by!(arg, *args)
|
86
|
+
where(arg, *args).take!
|
93
87
|
rescue RangeError
|
94
|
-
raise RecordNotFound
|
88
|
+
raise RecordNotFound.new("Couldn't find #{@klass.name} with an out of range value",
|
89
|
+
@klass.name)
|
95
90
|
end
|
96
91
|
|
97
92
|
# Gives a record (or N records if a parameter is supplied) without any implied
|
@@ -105,10 +100,10 @@ module ActiveRecord
|
|
105
100
|
limit ? limit(limit).to_a : find_take
|
106
101
|
end
|
107
102
|
|
108
|
-
# Same as
|
109
|
-
# is found. Note that
|
103
|
+
# Same as #take but raises ActiveRecord::RecordNotFound if no record
|
104
|
+
# is found. Note that #take! accepts no arguments.
|
110
105
|
def take!
|
111
|
-
take or raise RecordNotFound.new("Couldn't find #{@klass.name} with [#{arel.where_sql}]")
|
106
|
+
take or raise RecordNotFound.new("Couldn't find #{@klass.name} with [#{arel.where_sql(@klass.arel_engine)}]")
|
112
107
|
end
|
113
108
|
|
114
109
|
# Find the first record (or first N records if a parameter is supplied).
|
@@ -128,8 +123,8 @@ module ActiveRecord
|
|
128
123
|
end
|
129
124
|
end
|
130
125
|
|
131
|
-
# Same as
|
132
|
-
# is found. Note that
|
126
|
+
# Same as #first but raises ActiveRecord::RecordNotFound if no record
|
127
|
+
# is found. Note that #first! accepts no arguments.
|
133
128
|
def first!
|
134
129
|
find_nth! 0
|
135
130
|
end
|
@@ -161,10 +156,10 @@ module ActiveRecord
|
|
161
156
|
end
|
162
157
|
end
|
163
158
|
|
164
|
-
# Same as
|
165
|
-
# is found. Note that
|
159
|
+
# Same as #last but raises ActiveRecord::RecordNotFound if no record
|
160
|
+
# is found. Note that #last! accepts no arguments.
|
166
161
|
def last!
|
167
|
-
last or raise RecordNotFound.new("Couldn't find #{@klass.name} with [#{arel.where_sql}]")
|
162
|
+
last or raise RecordNotFound.new("Couldn't find #{@klass.name} with [#{arel.where_sql(@klass.arel_engine)}]")
|
168
163
|
end
|
169
164
|
|
170
165
|
# Find the second record.
|
@@ -177,7 +172,7 @@ module ActiveRecord
|
|
177
172
|
find_nth(1, offset_index)
|
178
173
|
end
|
179
174
|
|
180
|
-
# Same as
|
175
|
+
# Same as #second but raises ActiveRecord::RecordNotFound if no record
|
181
176
|
# is found.
|
182
177
|
def second!
|
183
178
|
find_nth! 1
|
@@ -193,7 +188,7 @@ module ActiveRecord
|
|
193
188
|
find_nth(2, offset_index)
|
194
189
|
end
|
195
190
|
|
196
|
-
# Same as
|
191
|
+
# Same as #third but raises ActiveRecord::RecordNotFound if no record
|
197
192
|
# is found.
|
198
193
|
def third!
|
199
194
|
find_nth! 2
|
@@ -209,7 +204,7 @@ module ActiveRecord
|
|
209
204
|
find_nth(3, offset_index)
|
210
205
|
end
|
211
206
|
|
212
|
-
# Same as
|
207
|
+
# Same as #fourth but raises ActiveRecord::RecordNotFound if no record
|
213
208
|
# is found.
|
214
209
|
def fourth!
|
215
210
|
find_nth! 3
|
@@ -225,7 +220,7 @@ module ActiveRecord
|
|
225
220
|
find_nth(4, offset_index)
|
226
221
|
end
|
227
222
|
|
228
|
-
# Same as
|
223
|
+
# Same as #fifth but raises ActiveRecord::RecordNotFound if no record
|
229
224
|
# is found.
|
230
225
|
def fifth!
|
231
226
|
find_nth! 4
|
@@ -241,14 +236,14 @@ module ActiveRecord
|
|
241
236
|
find_nth(41, offset_index)
|
242
237
|
end
|
243
238
|
|
244
|
-
# Same as
|
239
|
+
# Same as #forty_two but raises ActiveRecord::RecordNotFound if no record
|
245
240
|
# is found.
|
246
241
|
def forty_two!
|
247
242
|
find_nth! 41
|
248
243
|
end
|
249
244
|
|
250
|
-
# Returns
|
251
|
-
# conditions given, or
|
245
|
+
# Returns true if a record exists in the table that matches the +id+ or
|
246
|
+
# conditions given, or false otherwise. The argument can take six forms:
|
252
247
|
#
|
253
248
|
# * Integer - Finds the record with this primary key.
|
254
249
|
# * String - Finds the record with a primary key corresponding to this
|
@@ -261,7 +256,7 @@ module ActiveRecord
|
|
261
256
|
# * No args - Returns +false+ if the table is empty, +true+ otherwise.
|
262
257
|
#
|
263
258
|
# For more information about specifying conditions as a hash or array,
|
264
|
-
# see the Conditions section in the introduction to
|
259
|
+
# see the Conditions section in the introduction to ActiveRecord::Base.
|
265
260
|
#
|
266
261
|
# Note: You can't pass in a condition as a string (like <tt>name =
|
267
262
|
# 'Jamie'</tt>), since it would be sanitized and then queried against
|
@@ -299,11 +294,11 @@ module ActiveRecord
|
|
299
294
|
end
|
300
295
|
end
|
301
296
|
|
302
|
-
connection.select_value(relation, "#{name} Exists", relation.
|
297
|
+
connection.select_value(relation, "#{name} Exists", relation.bound_attributes) ? true : false
|
303
298
|
end
|
304
299
|
|
305
300
|
# This method is called whenever no records are found with either a single
|
306
|
-
# id or multiple ids and raises a
|
301
|
+
# id or multiple ids and raises a ActiveRecord::RecordNotFound exception.
|
307
302
|
#
|
308
303
|
# The error message is different depending on whether a single id or
|
309
304
|
# multiple ids are provided. If multiple ids are provided, then the number
|
@@ -311,7 +306,7 @@ module ActiveRecord
|
|
311
306
|
# the expected number of results should be provided in the +expected_size+
|
312
307
|
# argument.
|
313
308
|
def raise_record_not_found_exception!(ids, result_size, expected_size) #:nodoc:
|
314
|
-
conditions = arel.where_sql
|
309
|
+
conditions = arel.where_sql(@klass.arel_engine)
|
315
310
|
conditions = " [#{conditions}]" if conditions
|
316
311
|
|
317
312
|
if Array(ids).size == 1
|
@@ -353,7 +348,7 @@ module ActiveRecord
|
|
353
348
|
[]
|
354
349
|
else
|
355
350
|
arel = relation.arel
|
356
|
-
rows = connection.select_all(arel, 'SQL',
|
351
|
+
rows = connection.select_all(arel, 'SQL', relation.bound_attributes)
|
357
352
|
join_dependency.instantiate(rows, aliases)
|
358
353
|
end
|
359
354
|
end
|
@@ -385,7 +380,7 @@ module ActiveRecord
|
|
385
380
|
else
|
386
381
|
if relation.limit_value
|
387
382
|
limited_ids = limited_ids_for(relation)
|
388
|
-
limited_ids.empty? ? relation.none! : relation.where!(
|
383
|
+
limited_ids.empty? ? relation.none! : relation.where!(primary_key => limited_ids)
|
389
384
|
end
|
390
385
|
relation.except(:limit, :offset)
|
391
386
|
end
|
@@ -398,12 +393,12 @@ module ActiveRecord
|
|
398
393
|
relation = relation.except(:select).select(values).distinct!
|
399
394
|
arel = relation.arel
|
400
395
|
|
401
|
-
id_rows = @klass.connection.select_all(arel, 'SQL',
|
396
|
+
id_rows = @klass.connection.select_all(arel, 'SQL', relation.bound_attributes)
|
402
397
|
id_rows.map {|row| row[primary_key]}
|
403
398
|
end
|
404
399
|
|
405
400
|
def using_limitable_reflections?(reflections)
|
406
|
-
reflections.none?
|
401
|
+
reflections.none?(&:collection?)
|
407
402
|
end
|
408
403
|
|
409
404
|
protected
|
@@ -447,6 +442,8 @@ module ActiveRecord
|
|
447
442
|
end
|
448
443
|
|
449
444
|
def find_some(ids)
|
445
|
+
return find_some_ordered(ids) unless order_values.present?
|
446
|
+
|
450
447
|
result = where(primary_key => ids).to_a
|
451
448
|
|
452
449
|
expected_size =
|
@@ -468,6 +465,21 @@ module ActiveRecord
|
|
468
465
|
end
|
469
466
|
end
|
470
467
|
|
468
|
+
def find_some_ordered(ids)
|
469
|
+
ids = ids.slice(offset_value || 0, limit_value || ids.size) || []
|
470
|
+
|
471
|
+
result = except(:limit, :offset).where(primary_key => ids).to_a
|
472
|
+
|
473
|
+
if result.size == ids.size
|
474
|
+
pk_type = @klass.type_for_attribute(primary_key)
|
475
|
+
|
476
|
+
records_by_id = result.index_by(&:id)
|
477
|
+
ids.map { |id| records_by_id.fetch(pk_type.cast(id)) }
|
478
|
+
else
|
479
|
+
raise_record_not_found_exception!(ids, result.size, ids.size)
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
471
483
|
def find_take
|
472
484
|
if loaded?
|
473
485
|
@records.first
|
@@ -486,7 +498,7 @@ module ActiveRecord
|
|
486
498
|
end
|
487
499
|
|
488
500
|
def find_nth!(index)
|
489
|
-
find_nth(index, offset_index) or raise RecordNotFound.new("Couldn't find #{@klass.name} with [#{arel.where_sql}]")
|
501
|
+
find_nth(index, offset_index) or raise RecordNotFound.new("Couldn't find #{@klass.name} with [#{arel.where_sql(@klass.arel_engine)}]")
|
490
502
|
end
|
491
503
|
|
492
504
|
def find_nth_with_limit(offset, limit)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Relation
|
3
|
+
class FromClause # :nodoc:
|
4
|
+
attr_reader :value, :name
|
5
|
+
|
6
|
+
def initialize(value, name)
|
7
|
+
@value = value
|
8
|
+
@name = name
|
9
|
+
end
|
10
|
+
|
11
|
+
def binds
|
12
|
+
if value.is_a?(Relation)
|
13
|
+
value.bound_attributes
|
14
|
+
else
|
15
|
+
[]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def merge(other)
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def empty?
|
24
|
+
value.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.empty
|
28
|
+
new(nil, nil)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'active_support/core_ext/hash/keys'
|
2
|
-
require "set"
|
3
2
|
|
4
3
|
module ActiveRecord
|
5
4
|
class Relation
|
@@ -22,7 +21,7 @@ module ActiveRecord
|
|
22
21
|
# build a relation to merge in rather than directly merging
|
23
22
|
# the values.
|
24
23
|
def other
|
25
|
-
other = Relation.create(relation.klass, relation.table)
|
24
|
+
other = Relation.create(relation.klass, relation.table, relation.predicate_builder)
|
26
25
|
hash.each { |k, v|
|
27
26
|
if k == :joins
|
28
27
|
if Hash === v
|
@@ -49,10 +48,9 @@ module ActiveRecord
|
|
49
48
|
@other = other
|
50
49
|
end
|
51
50
|
|
52
|
-
NORMAL_VALUES = Relation::
|
53
|
-
Relation::
|
54
|
-
[:includes, :preload, :joins, :
|
55
|
-
|
51
|
+
NORMAL_VALUES = Relation::VALUE_METHODS -
|
52
|
+
Relation::CLAUSE_METHODS -
|
53
|
+
[:includes, :preload, :joins, :order, :reverse_order, :lock, :create_with, :reordering] # :nodoc:
|
56
54
|
|
57
55
|
def normal_values
|
58
56
|
NORMAL_VALUES
|
@@ -76,6 +74,7 @@ module ActiveRecord
|
|
76
74
|
|
77
75
|
merge_multi_values
|
78
76
|
merge_single_values
|
77
|
+
merge_clauses
|
79
78
|
merge_preloads
|
80
79
|
merge_joins
|
81
80
|
|
@@ -130,20 +129,6 @@ module ActiveRecord
|
|
130
129
|
end
|
131
130
|
|
132
131
|
def merge_multi_values
|
133
|
-
lhs_wheres = relation.where_values
|
134
|
-
rhs_wheres = other.where_values
|
135
|
-
|
136
|
-
lhs_binds = relation.bind_values
|
137
|
-
rhs_binds = other.bind_values
|
138
|
-
|
139
|
-
removed, kept = partition_overwrites(lhs_wheres, rhs_wheres)
|
140
|
-
|
141
|
-
where_values = kept + rhs_wheres
|
142
|
-
bind_values = filter_binds(lhs_binds, removed) + rhs_binds
|
143
|
-
|
144
|
-
relation.where_values = where_values
|
145
|
-
relation.bind_values = bind_values
|
146
|
-
|
147
132
|
if other.reordering_value
|
148
133
|
# override any order specified in the original relation
|
149
134
|
relation.reorder! other.order_values
|
@@ -156,36 +141,22 @@ module ActiveRecord
|
|
156
141
|
end
|
157
142
|
|
158
143
|
def merge_single_values
|
159
|
-
relation.
|
160
|
-
relation.lock_value = other.lock_value unless relation.lock_value
|
144
|
+
relation.lock_value ||= other.lock_value
|
161
145
|
|
162
146
|
unless other.create_with_value.blank?
|
163
147
|
relation.create_with_value = (relation.create_with_value || {}).merge(other.create_with_value)
|
164
148
|
end
|
165
149
|
end
|
166
150
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
set = Set.new removed_wheres.map { |x| x.left.name.to_s }
|
171
|
-
lhs_binds.dup.delete_if { |col,_| set.include? col.name }
|
151
|
+
CLAUSE_METHOD_NAMES = CLAUSE_METHODS.map do |name|
|
152
|
+
["#{name}_clause", "#{name}_clause="]
|
172
153
|
end
|
173
154
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
return [[], lhs_wheres]
|
180
|
-
end
|
181
|
-
|
182
|
-
nodes = rhs_wheres.find_all do |w|
|
183
|
-
w.respond_to?(:operator) && w.operator == :==
|
184
|
-
end
|
185
|
-
seen = Set.new(nodes) { |node| node.left }
|
186
|
-
|
187
|
-
lhs_wheres.partition do |w|
|
188
|
-
w.respond_to?(:operator) && w.operator == :== && seen.include?(w.left)
|
155
|
+
def merge_clauses
|
156
|
+
CLAUSE_METHOD_NAMES.each do |(reader, writer)|
|
157
|
+
clause = relation.send(reader)
|
158
|
+
other_clause = other.send(reader)
|
159
|
+
relation.send(writer, clause.merge(other_clause))
|
189
160
|
end
|
190
161
|
end
|
191
162
|
end
|