activerecord 4.2.11.1 → 5.2.4
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 +4 -4
- data/CHANGELOG.md +579 -1635
- data/MIT-LICENSE +2 -2
- data/README.rdoc +10 -11
- data/examples/performance.rb +32 -31
- data/examples/simple.rb +5 -4
- data/lib/active_record/aggregations.rb +263 -249
- data/lib/active_record/association_relation.rb +11 -6
- data/lib/active_record/associations/alias_tracker.rb +29 -35
- data/lib/active_record/associations/association.rb +77 -43
- data/lib/active_record/associations/association_scope.rb +106 -133
- data/lib/active_record/associations/belongs_to_association.rb +52 -41
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
- data/lib/active_record/associations/builder/association.rb +29 -38
- data/lib/active_record/associations/builder/belongs_to.rb +77 -30
- data/lib/active_record/associations/builder/collection_association.rb +9 -22
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +42 -35
- data/lib/active_record/associations/builder/has_many.rb +6 -4
- data/lib/active_record/associations/builder/has_one.rb +13 -6
- data/lib/active_record/associations/builder/singular_association.rb +15 -11
- data/lib/active_record/associations/collection_association.rb +139 -280
- data/lib/active_record/associations/collection_proxy.rb +231 -133
- data/lib/active_record/associations/foreign_association.rb +3 -1
- data/lib/active_record/associations/has_many_association.rb +34 -89
- data/lib/active_record/associations/has_many_through_association.rb +49 -76
- data/lib/active_record/associations/has_one_association.rb +38 -24
- data/lib/active_record/associations/has_one_through_association.rb +18 -9
- data/lib/active_record/associations/join_dependency/join_association.rb +40 -87
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
- data/lib/active_record/associations/join_dependency.rb +133 -159
- data/lib/active_record/associations/preloader/association.rb +85 -120
- data/lib/active_record/associations/preloader/through_association.rb +85 -74
- data/lib/active_record/associations/preloader.rb +81 -91
- data/lib/active_record/associations/singular_association.rb +27 -34
- data/lib/active_record/associations/through_association.rb +38 -18
- data/lib/active_record/associations.rb +1732 -1597
- data/lib/active_record/attribute_assignment.rb +58 -182
- data/lib/active_record/attribute_decorators.rb +39 -15
- data/lib/active_record/attribute_methods/before_type_cast.rb +10 -8
- data/lib/active_record/attribute_methods/dirty.rb +94 -135
- data/lib/active_record/attribute_methods/primary_key.rb +86 -71
- data/lib/active_record/attribute_methods/query.rb +4 -2
- data/lib/active_record/attribute_methods/read.rb +45 -63
- data/lib/active_record/attribute_methods/serialization.rb +40 -20
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +58 -36
- data/lib/active_record/attribute_methods/write.rb +30 -45
- data/lib/active_record/attribute_methods.rb +166 -109
- data/lib/active_record/attributes.rb +201 -82
- data/lib/active_record/autosave_association.rb +94 -36
- data/lib/active_record/base.rb +57 -44
- data/lib/active_record/callbacks.rb +97 -57
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +24 -12
- data/lib/active_record/collection_cache_key.rb +53 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +712 -290
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +10 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +237 -90
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +71 -21
- data/lib/active_record/connection_adapters/abstract/quoting.rb +118 -52
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +67 -46
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +318 -217
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +81 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +570 -228
- data/lib/active_record/connection_adapters/abstract/transaction.rb +138 -70
- data/lib/active_record/connection_adapters/abstract_adapter.rb +325 -202
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +542 -601
- data/lib/active_record/connection_adapters/column.rb +50 -41
- data/lib/active_record/connection_adapters/connection_specification.rb +147 -135
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +41 -180
- data/lib/active_record/connection_adapters/postgresql/column.rb +35 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +45 -114
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -58
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +10 -6
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -22
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -7
- data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +55 -53
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +107 -47
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +144 -90
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -284
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +432 -323
- data/lib/active_record/connection_adapters/schema_cache.rb +48 -24
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +269 -308
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +40 -27
- data/lib/active_record/core.rb +178 -198
- data/lib/active_record/counter_cache.rb +79 -36
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -105
- data/lib/active_record/enum.rb +135 -88
- data/lib/active_record/errors.rb +179 -52
- data/lib/active_record/explain.rb +23 -11
- data/lib/active_record/explain_registry.rb +4 -2
- data/lib/active_record/explain_subscriber.rb +10 -5
- data/lib/active_record/fixture_set/file.rb +35 -9
- data/lib/active_record/fixtures.rb +188 -132
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +148 -112
- data/lib/active_record/integration.rb +70 -28
- data/lib/active_record/internal_metadata.rb +45 -0
- data/lib/active_record/legacy_yaml_adapter.rb +21 -3
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +88 -96
- data/lib/active_record/locking/pessimistic.rb +15 -3
- data/lib/active_record/log_subscriber.rb +95 -33
- data/lib/active_record/migration/command_recorder.rb +133 -90
- data/lib/active_record/migration/compatibility.rb +217 -0
- data/lib/active_record/migration/join_table.rb +8 -6
- data/lib/active_record/migration.rb +581 -282
- data/lib/active_record/model_schema.rb +290 -111
- data/lib/active_record/nested_attributes.rb +264 -222
- data/lib/active_record/no_touching.rb +7 -1
- data/lib/active_record/null_relation.rb +24 -37
- data/lib/active_record/persistence.rb +347 -119
- data/lib/active_record/query_cache.rb +13 -24
- data/lib/active_record/querying.rb +19 -17
- data/lib/active_record/railtie.rb +94 -32
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +9 -3
- data/lib/active_record/railties/databases.rake +149 -156
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +414 -267
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/batches.rb +204 -55
- data/lib/active_record/relation/calculations.rb +256 -248
- data/lib/active_record/relation/delegation.rb +67 -60
- data/lib/active_record/relation/finder_methods.rb +288 -239
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +86 -86
- data/lib/active_record/relation/predicate_builder/array_handler.rb +24 -24
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/predicate_builder.rb +116 -119
- data/lib/active_record/relation/query_attribute.rb +45 -0
- data/lib/active_record/relation/query_methods.rb +448 -393
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +11 -13
- data/lib/active_record/relation/where_clause.rb +186 -0
- data/lib/active_record/relation/where_clause_factory.rb +34 -0
- data/lib/active_record/relation.rb +287 -340
- data/lib/active_record/result.rb +54 -36
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +155 -124
- data/lib/active_record/schema.rb +30 -24
- data/lib/active_record/schema_dumper.rb +91 -87
- data/lib/active_record/schema_migration.rb +19 -16
- data/lib/active_record/scoping/default.rb +102 -85
- data/lib/active_record/scoping/named.rb +81 -32
- data/lib/active_record/scoping.rb +45 -26
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +5 -5
- data/lib/active_record/statement_cache.rb +45 -35
- data/lib/active_record/store.rb +42 -36
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +82 -0
- data/lib/active_record/tasks/database_tasks.rb +134 -96
- data/lib/active_record/tasks/mysql_database_tasks.rb +56 -100
- data/lib/active_record/tasks/postgresql_database_tasks.rb +83 -41
- data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -16
- data/lib/active_record/timestamp.rb +70 -38
- data/lib/active_record/touch_later.rb +64 -0
- data/lib/active_record/transactions.rb +199 -124
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type/adapter_specific_registry.rb +136 -0
- data/lib/active_record/type/date.rb +4 -45
- data/lib/active_record/type/date_time.rb +4 -49
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +24 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +11 -16
- data/lib/active_record/type/type_map.rb +15 -17
- data/lib/active_record/type/unsigned_integer.rb +9 -7
- data/lib/active_record/type.rb +79 -23
- data/lib/active_record/type_caster/connection.rb +33 -0
- data/lib/active_record/type_caster/map.rb +23 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +13 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +40 -41
- data/lib/active_record/validations.rb +38 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +34 -22
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -35
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +8 -3
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +8 -1
- data/lib/rails/generators/active_record/migration.rb +18 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +18 -22
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +3 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +72 -49
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute.rb +0 -163
- data/lib/active_record/attribute_set/builder.rb +0 -106
- data/lib/active_record/attribute_set.rb +0 -81
- 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/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- 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/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/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -110
@@ -1,12 +1,13 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/string/filters"
|
3
4
|
|
4
5
|
module ActiveRecord
|
5
6
|
module FinderMethods
|
6
|
-
ONE_AS_ONE =
|
7
|
+
ONE_AS_ONE = "1 AS one"
|
7
8
|
|
8
9
|
# 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
|
10
|
+
# If one or more records can not be found for the requested ids, then RecordNotFound will be raised. If the primary key
|
10
11
|
# is an integer, find by id coerces its arguments using +to_i+.
|
11
12
|
#
|
12
13
|
# Person.find(1) # returns the object for ID = 1
|
@@ -17,11 +18,10 @@ module ActiveRecord
|
|
17
18
|
# Person.find([1]) # returns an array for the object with ID = 1
|
18
19
|
# Person.where("administrator = 1").order("created_on DESC").find(1)
|
19
20
|
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
# option if you want the results are sorted.
|
21
|
+
# NOTE: The returned records are in the same order as the ids you provide.
|
22
|
+
# If you want the results to be sorted by database, you can use ActiveRecord::QueryMethods#where
|
23
|
+
# method and provide an explicit ActiveRecord::QueryMethods#order option.
|
24
|
+
# But ActiveRecord::QueryMethods#where method doesn't raise ActiveRecord::RecordNotFound.
|
25
25
|
#
|
26
26
|
# ==== Find with lock
|
27
27
|
#
|
@@ -37,7 +37,7 @@ module ActiveRecord
|
|
37
37
|
# person.save!
|
38
38
|
# end
|
39
39
|
#
|
40
|
-
# ==== Variations of
|
40
|
+
# ==== Variations of #find
|
41
41
|
#
|
42
42
|
# Person.where(name: 'Spartacus', rating: 4)
|
43
43
|
# # returns a chainable list (which can be empty).
|
@@ -45,13 +45,13 @@ module ActiveRecord
|
|
45
45
|
# Person.find_by(name: 'Spartacus', rating: 4)
|
46
46
|
# # returns the first item or nil.
|
47
47
|
#
|
48
|
-
# Person.
|
48
|
+
# Person.find_or_initialize_by(name: 'Spartacus', rating: 4)
|
49
49
|
# # returns the first item or returns a new instance (requires you call .save to persist against the database).
|
50
50
|
#
|
51
|
-
# Person.
|
52
|
-
# # returns the first item or creates it and returns it
|
51
|
+
# Person.find_or_create_by(name: 'Spartacus', rating: 4)
|
52
|
+
# # returns the first item or creates it and returns it.
|
53
53
|
#
|
54
|
-
# ==== Alternatives for
|
54
|
+
# ==== Alternatives for #find
|
55
55
|
#
|
56
56
|
# Person.where(name: 'Spartacus', rating: 4).exists?(conditions = :none)
|
57
57
|
# # returns a boolean indicating if any record with the given conditions exist.
|
@@ -60,16 +60,13 @@ module ActiveRecord
|
|
60
60
|
# # returns a chainable list of instances with only the mentioned fields.
|
61
61
|
#
|
62
62
|
# Person.where(name: 'Spartacus', rating: 4).ids
|
63
|
-
# # returns an Array of ids
|
63
|
+
# # returns an Array of ids.
|
64
64
|
#
|
65
65
|
# Person.where(name: 'Spartacus', rating: 4).pluck(:field1, :field2)
|
66
|
-
# # returns an Array of the required fields
|
66
|
+
# # returns an Array of the required fields.
|
67
67
|
def find(*args)
|
68
|
-
if block_given?
|
69
|
-
|
70
|
-
else
|
71
|
-
find_with_ids(*args)
|
72
|
-
end
|
68
|
+
return super if block_given?
|
69
|
+
find_with_ids(*args)
|
73
70
|
end
|
74
71
|
|
75
72
|
# Finds the first record matching the specified conditions. There
|
@@ -80,18 +77,19 @@ module ActiveRecord
|
|
80
77
|
#
|
81
78
|
# Post.find_by name: 'Spartacus', rating: 4
|
82
79
|
# Post.find_by "published_at < ?", 2.weeks.ago
|
83
|
-
def find_by(*args)
|
84
|
-
where(*args).take
|
85
|
-
rescue RangeError
|
80
|
+
def find_by(arg, *args)
|
81
|
+
where(arg, *args).take
|
82
|
+
rescue ::RangeError
|
86
83
|
nil
|
87
84
|
end
|
88
85
|
|
89
|
-
# Like
|
90
|
-
# an
|
91
|
-
def find_by!(*args)
|
92
|
-
where(*args).take!
|
93
|
-
rescue RangeError
|
94
|
-
raise RecordNotFound
|
86
|
+
# Like #find_by, except that if no record is found, raises
|
87
|
+
# an ActiveRecord::RecordNotFound error.
|
88
|
+
def find_by!(arg, *args)
|
89
|
+
where(arg, *args).take!
|
90
|
+
rescue ::RangeError
|
91
|
+
raise RecordNotFound.new("Couldn't find #{@klass.name} with an out of range value",
|
92
|
+
@klass.name, @klass.primary_key)
|
95
93
|
end
|
96
94
|
|
97
95
|
# Gives a record (or N records if a parameter is supplied) without any implied
|
@@ -102,13 +100,13 @@ module ActiveRecord
|
|
102
100
|
# Person.take(5) # returns 5 objects fetched by SELECT * FROM people LIMIT 5
|
103
101
|
# Person.where(["name LIKE '%?'", name]).take
|
104
102
|
def take(limit = nil)
|
105
|
-
limit ?
|
103
|
+
limit ? find_take_with_limit(limit) : find_take
|
106
104
|
end
|
107
105
|
|
108
|
-
# Same as
|
109
|
-
# is found. Note that
|
106
|
+
# Same as #take but raises ActiveRecord::RecordNotFound if no record
|
107
|
+
# is found. Note that #take! accepts no arguments.
|
110
108
|
def take!
|
111
|
-
take
|
109
|
+
take || raise_record_not_found_exception!
|
112
110
|
end
|
113
111
|
|
114
112
|
# Find the first record (or first N records if a parameter is supplied).
|
@@ -122,16 +120,16 @@ module ActiveRecord
|
|
122
120
|
#
|
123
121
|
def first(limit = nil)
|
124
122
|
if limit
|
125
|
-
find_nth_with_limit(
|
123
|
+
find_nth_with_limit(0, limit)
|
126
124
|
else
|
127
|
-
find_nth
|
125
|
+
find_nth 0
|
128
126
|
end
|
129
127
|
end
|
130
128
|
|
131
|
-
# Same as
|
132
|
-
# is found. Note that
|
129
|
+
# Same as #first but raises ActiveRecord::RecordNotFound if no record
|
130
|
+
# is found. Note that #first! accepts no arguments.
|
133
131
|
def first!
|
134
|
-
|
132
|
+
first || raise_record_not_found_exception!
|
135
133
|
end
|
136
134
|
|
137
135
|
# Find the last record (or last N records if a parameter is supplied).
|
@@ -150,21 +148,18 @@ module ActiveRecord
|
|
150
148
|
#
|
151
149
|
# [#<Person id:4>, #<Person id:3>, #<Person id:2>]
|
152
150
|
def last(limit = nil)
|
153
|
-
if
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
else
|
160
|
-
find_last
|
161
|
-
end
|
151
|
+
return find_last(limit) if loaded? || has_limit_or_offset?
|
152
|
+
|
153
|
+
result = ordered_relation.limit(limit)
|
154
|
+
result = result.reverse_order!
|
155
|
+
|
156
|
+
limit ? result.reverse : result.first
|
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
|
162
|
+
last || raise_record_not_found_exception!
|
168
163
|
end
|
169
164
|
|
170
165
|
# Find the second record.
|
@@ -174,13 +169,13 @@ module ActiveRecord
|
|
174
169
|
# Person.offset(3).second # returns the second object from OFFSET 3 (which is OFFSET 4)
|
175
170
|
# Person.where(["user_name = :u", { u: user_name }]).second
|
176
171
|
def second
|
177
|
-
find_nth
|
172
|
+
find_nth 1
|
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
|
+
second || raise_record_not_found_exception!
|
184
179
|
end
|
185
180
|
|
186
181
|
# Find the third record.
|
@@ -190,13 +185,13 @@ module ActiveRecord
|
|
190
185
|
# Person.offset(3).third # returns the third object from OFFSET 3 (which is OFFSET 5)
|
191
186
|
# Person.where(["user_name = :u", { u: user_name }]).third
|
192
187
|
def third
|
193
|
-
find_nth
|
188
|
+
find_nth 2
|
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
|
+
third || raise_record_not_found_exception!
|
200
195
|
end
|
201
196
|
|
202
197
|
# Find the fourth record.
|
@@ -206,13 +201,13 @@ module ActiveRecord
|
|
206
201
|
# Person.offset(3).fourth # returns the fourth object from OFFSET 3 (which is OFFSET 6)
|
207
202
|
# Person.where(["user_name = :u", { u: user_name }]).fourth
|
208
203
|
def fourth
|
209
|
-
find_nth
|
204
|
+
find_nth 3
|
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
|
+
fourth || raise_record_not_found_exception!
|
216
211
|
end
|
217
212
|
|
218
213
|
# Find the fifth record.
|
@@ -222,13 +217,13 @@ module ActiveRecord
|
|
222
217
|
# Person.offset(3).fifth # returns the fifth object from OFFSET 3 (which is OFFSET 7)
|
223
218
|
# Person.where(["user_name = :u", { u: user_name }]).fifth
|
224
219
|
def fifth
|
225
|
-
find_nth
|
220
|
+
find_nth 4
|
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
|
+
fifth || raise_record_not_found_exception!
|
232
227
|
end
|
233
228
|
|
234
229
|
# Find the forty-second record. Also known as accessing "the reddit".
|
@@ -238,17 +233,49 @@ module ActiveRecord
|
|
238
233
|
# Person.offset(3).forty_two # returns the forty-second object from OFFSET 3 (which is OFFSET 44)
|
239
234
|
# Person.where(["user_name = :u", { u: user_name }]).forty_two
|
240
235
|
def forty_two
|
241
|
-
find_nth
|
236
|
+
find_nth 41
|
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
|
+
forty_two || raise_record_not_found_exception!
|
248
243
|
end
|
249
244
|
|
250
|
-
#
|
251
|
-
#
|
245
|
+
# Find the third-to-last record.
|
246
|
+
# If no order is defined it will order by primary key.
|
247
|
+
#
|
248
|
+
# Person.third_to_last # returns the third-to-last object fetched by SELECT * FROM people
|
249
|
+
# Person.offset(3).third_to_last # returns the third-to-last object from OFFSET 3
|
250
|
+
# Person.where(["user_name = :u", { u: user_name }]).third_to_last
|
251
|
+
def third_to_last
|
252
|
+
find_nth_from_last 3
|
253
|
+
end
|
254
|
+
|
255
|
+
# Same as #third_to_last but raises ActiveRecord::RecordNotFound if no record
|
256
|
+
# is found.
|
257
|
+
def third_to_last!
|
258
|
+
third_to_last || raise_record_not_found_exception!
|
259
|
+
end
|
260
|
+
|
261
|
+
# Find the second-to-last record.
|
262
|
+
# If no order is defined it will order by primary key.
|
263
|
+
#
|
264
|
+
# Person.second_to_last # returns the second-to-last object fetched by SELECT * FROM people
|
265
|
+
# Person.offset(3).second_to_last # returns the second-to-last object from OFFSET 3
|
266
|
+
# Person.where(["user_name = :u", { u: user_name }]).second_to_last
|
267
|
+
def second_to_last
|
268
|
+
find_nth_from_last 2
|
269
|
+
end
|
270
|
+
|
271
|
+
# Same as #second_to_last but raises ActiveRecord::RecordNotFound if no record
|
272
|
+
# is found.
|
273
|
+
def second_to_last!
|
274
|
+
second_to_last || raise_record_not_found_exception!
|
275
|
+
end
|
276
|
+
|
277
|
+
# Returns true if a record exists in the table that matches the +id+ or
|
278
|
+
# conditions given, or false otherwise. The argument can take six forms:
|
252
279
|
#
|
253
280
|
# * Integer - Finds the record with this primary key.
|
254
281
|
# * String - Finds the record with a primary key corresponding to this
|
@@ -258,10 +285,10 @@ module ActiveRecord
|
|
258
285
|
# * Hash - Finds the record that matches these +find+-style conditions
|
259
286
|
# (such as <tt>{name: 'David'}</tt>).
|
260
287
|
# * +false+ - Returns always +false+.
|
261
|
-
# * No args - Returns +false+ if the
|
288
|
+
# * No args - Returns +false+ if the relation is empty, +true+ otherwise.
|
262
289
|
#
|
263
290
|
# For more information about specifying conditions as a hash or array,
|
264
|
-
# see the Conditions section in the introduction to
|
291
|
+
# see the Conditions section in the introduction to ActiveRecord::Base.
|
265
292
|
#
|
266
293
|
# Note: You can't pass in a condition as a string (like <tt>name =
|
267
294
|
# 'Jamie'</tt>), since it would be sanitized and then queried against
|
@@ -274,243 +301,265 @@ module ActiveRecord
|
|
274
301
|
# Person.exists?(name: 'David')
|
275
302
|
# Person.exists?(false)
|
276
303
|
# Person.exists?
|
304
|
+
# Person.where(name: 'Spartacus', rating: 4).exists?
|
277
305
|
def exists?(conditions = :none)
|
278
306
|
if Base === conditions
|
279
|
-
|
280
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
307
|
+
raise ArgumentError, <<-MSG.squish
|
281
308
|
You are passing an instance of ActiveRecord::Base to `exists?`.
|
282
|
-
Please pass the id of the object by calling `.id
|
309
|
+
Please pass the id of the object by calling `.id`.
|
283
310
|
MSG
|
284
311
|
end
|
285
312
|
|
286
|
-
return false if !conditions
|
287
|
-
|
288
|
-
relation = apply_join_dependency(self, construct_join_dependency)
|
289
|
-
return false if ActiveRecord::NullRelation === relation
|
313
|
+
return false if !conditions || limit_value == 0
|
290
314
|
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
when Array, Hash
|
295
|
-
relation = relation.where(conditions)
|
296
|
-
else
|
297
|
-
unless conditions == :none
|
298
|
-
relation = relation.where(primary_key => conditions)
|
299
|
-
end
|
315
|
+
if eager_loading?
|
316
|
+
relation = apply_join_dependency(eager_loading: false)
|
317
|
+
return relation.exists?(conditions)
|
300
318
|
end
|
301
319
|
|
302
|
-
|
320
|
+
relation = construct_relation_for_exists(conditions)
|
321
|
+
|
322
|
+
skip_query_cache_if_necessary { connection.select_one(relation.arel, "#{name} Exists") } ? true : false
|
323
|
+
rescue ::RangeError
|
324
|
+
false
|
303
325
|
end
|
304
326
|
|
305
327
|
# This method is called whenever no records are found with either a single
|
306
|
-
# id or multiple ids and raises
|
328
|
+
# id or multiple ids and raises an ActiveRecord::RecordNotFound exception.
|
307
329
|
#
|
308
330
|
# The error message is different depending on whether a single id or
|
309
331
|
# multiple ids are provided. If multiple ids are provided, then the number
|
310
332
|
# of results obtained should be provided in the +result_size+ argument and
|
311
333
|
# the expected number of results should be provided in the +expected_size+
|
312
334
|
# argument.
|
313
|
-
def raise_record_not_found_exception!(ids, result_size, expected_size)
|
314
|
-
conditions = arel.where_sql
|
335
|
+
def raise_record_not_found_exception!(ids = nil, result_size = nil, expected_size = nil, key = primary_key, not_found_ids = nil) # :nodoc:
|
336
|
+
conditions = arel.where_sql(@klass)
|
315
337
|
conditions = " [#{conditions}]" if conditions
|
316
|
-
|
317
|
-
|
318
|
-
|
338
|
+
name = @klass.name
|
339
|
+
|
340
|
+
if ids.nil?
|
341
|
+
error = "Couldn't find #{name}".dup
|
342
|
+
error << " with#{conditions}" if conditions
|
343
|
+
raise RecordNotFound.new(error, name, key)
|
344
|
+
elsif Array(ids).size == 1
|
345
|
+
error = "Couldn't find #{name} with '#{key}'=#{ids}#{conditions}"
|
346
|
+
raise RecordNotFound.new(error, name, key, ids)
|
319
347
|
else
|
320
|
-
error = "Couldn't find all #{
|
321
|
-
error << "(#{ids.join(", ")})#{conditions} (found #{result_size} results, but was looking for #{expected_size})"
|
348
|
+
error = "Couldn't find all #{name.pluralize} with '#{key}': ".dup
|
349
|
+
error << "(#{ids.join(", ")})#{conditions} (found #{result_size} results, but was looking for #{expected_size})."
|
350
|
+
error << " Couldn't find #{name.pluralize(not_found_ids.size)} with #{key.to_s.pluralize(not_found_ids.size)} #{not_found_ids.join(', ')}." if not_found_ids
|
351
|
+
raise RecordNotFound.new(error, name, key, ids)
|
322
352
|
end
|
323
|
-
|
324
|
-
raise RecordNotFound, error
|
325
353
|
end
|
326
354
|
|
327
355
|
private
|
328
356
|
|
329
|
-
|
330
|
-
|
331
|
-
|
357
|
+
def offset_index
|
358
|
+
offset_value || 0
|
359
|
+
end
|
332
360
|
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
#
|
337
|
-
# failing to do so means that in cases like activerecord/test/cases/associations/inner_join_association_test.rb:136
|
338
|
-
# incorrect SQL is generated. In that case, the join dependency for
|
339
|
-
# SpecialCategorizations is constructed without knowledge of the
|
340
|
-
# preexisting join in joins_values to categorizations (by way of
|
341
|
-
# the `has_many :through` for categories).
|
342
|
-
#
|
343
|
-
join_dependency = construct_join_dependency(joins_values)
|
344
|
-
|
345
|
-
aliases = join_dependency.aliases
|
346
|
-
relation = select aliases.columns
|
347
|
-
relation = apply_join_dependency(relation, join_dependency)
|
348
|
-
|
349
|
-
if block_given?
|
350
|
-
yield relation
|
351
|
-
else
|
352
|
-
if ActiveRecord::NullRelation === relation
|
353
|
-
[]
|
361
|
+
def construct_relation_for_exists(conditions)
|
362
|
+
if distinct_value && offset_value
|
363
|
+
relation = except(:order).limit!(1)
|
354
364
|
else
|
355
|
-
|
356
|
-
rows = connection.select_all(arel, 'SQL', arel.bind_values + relation.bind_values)
|
357
|
-
join_dependency.instantiate(rows, aliases)
|
365
|
+
relation = except(:select, :distinct, :order)._select!(ONE_AS_ONE).limit!(1)
|
358
366
|
end
|
359
|
-
end
|
360
|
-
end
|
361
367
|
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
368
|
+
case conditions
|
369
|
+
when Array, Hash
|
370
|
+
relation.where!(conditions) unless conditions.empty?
|
371
|
+
else
|
372
|
+
relation.where!(primary_key => conditions) unless conditions == :none
|
373
|
+
end
|
366
374
|
|
367
|
-
|
368
|
-
from = arel.froms.first
|
369
|
-
if Arel::Table === from
|
370
|
-
apply_join_dependency(self, construct_join_dependency(joins_values))
|
371
|
-
else
|
372
|
-
# FIXME: as far as I can tell, `from` will always be an Arel::Table.
|
373
|
-
# There are no tests that test this branch, but presumably it's
|
374
|
-
# possible for `from` to be a list?
|
375
|
-
apply_join_dependency(self, construct_join_dependency(from))
|
375
|
+
relation
|
376
376
|
end
|
377
|
-
end
|
378
377
|
|
379
|
-
|
380
|
-
|
381
|
-
|
378
|
+
def construct_join_dependency
|
379
|
+
including = eager_load_values + includes_values
|
380
|
+
ActiveRecord::Associations::JoinDependency.new(
|
381
|
+
klass, table, including
|
382
|
+
)
|
383
|
+
end
|
382
384
|
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
385
|
+
def apply_join_dependency(eager_loading: group_values.empty?)
|
386
|
+
join_dependency = construct_join_dependency
|
387
|
+
relation = except(:includes, :eager_load, :preload).joins!(join_dependency)
|
388
|
+
|
389
|
+
if eager_loading && !using_limitable_reflections?(join_dependency.reflections)
|
390
|
+
if has_limit_or_offset?
|
391
|
+
limited_ids = limited_ids_for(relation)
|
392
|
+
limited_ids.empty? ? relation.none! : relation.where!(primary_key => limited_ids)
|
393
|
+
end
|
394
|
+
relation.limit_value = relation.offset_value = nil
|
395
|
+
end
|
396
|
+
|
397
|
+
if block_given?
|
398
|
+
yield relation, join_dependency
|
399
|
+
else
|
400
|
+
relation
|
389
401
|
end
|
390
|
-
relation.except(:limit, :offset)
|
391
402
|
end
|
392
|
-
end
|
393
403
|
|
394
|
-
|
395
|
-
|
396
|
-
|
404
|
+
def limited_ids_for(relation)
|
405
|
+
values = @klass.connection.columns_for_distinct(
|
406
|
+
connection.column_name_from_arel_node(arel_attribute(primary_key)),
|
407
|
+
relation.order_values
|
408
|
+
)
|
397
409
|
|
398
|
-
|
399
|
-
arel = relation.arel
|
410
|
+
relation = relation.except(:select).select(values).distinct!
|
400
411
|
|
401
|
-
|
402
|
-
|
403
|
-
|
412
|
+
id_rows = skip_query_cache_if_necessary { @klass.connection.select_all(relation.arel, "SQL") }
|
413
|
+
id_rows.map { |row| row[primary_key] }
|
414
|
+
end
|
404
415
|
|
405
|
-
|
406
|
-
|
407
|
-
|
416
|
+
def using_limitable_reflections?(reflections)
|
417
|
+
reflections.none?(&:collection?)
|
418
|
+
end
|
408
419
|
|
409
|
-
|
420
|
+
def find_with_ids(*ids)
|
421
|
+
raise UnknownPrimaryKey.new(@klass) if primary_key.nil?
|
410
422
|
|
411
|
-
|
412
|
-
|
423
|
+
expects_array = ids.first.kind_of?(Array)
|
424
|
+
return [] if expects_array && ids.first.empty?
|
413
425
|
|
414
|
-
|
415
|
-
return ids.first if expects_array && ids.first.empty?
|
426
|
+
ids = ids.flatten.compact.uniq
|
416
427
|
|
417
|
-
|
428
|
+
model_name = @klass.name
|
418
429
|
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
430
|
+
case ids.size
|
431
|
+
when 0
|
432
|
+
error_message = "Couldn't find #{model_name} without an ID"
|
433
|
+
raise RecordNotFound.new(error_message, model_name, primary_key)
|
434
|
+
when 1
|
435
|
+
result = find_one(ids.first)
|
436
|
+
expects_array ? [ result ] : result
|
437
|
+
else
|
438
|
+
find_some(ids)
|
439
|
+
end
|
440
|
+
rescue ::RangeError
|
441
|
+
error_message = "Couldn't find #{model_name} with an out of range ID"
|
442
|
+
raise RecordNotFound.new(error_message, model_name, primary_key, ids)
|
427
443
|
end
|
428
|
-
rescue RangeError
|
429
|
-
raise RecordNotFound, "Couldn't find #{@klass.name} with an out of range ID"
|
430
|
-
end
|
431
444
|
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
445
|
+
def find_one(id)
|
446
|
+
if ActiveRecord::Base === id
|
447
|
+
raise ArgumentError, <<-MSG.squish
|
448
|
+
You are passing an instance of ActiveRecord::Base to `find`.
|
449
|
+
Please pass the id of the object by calling `.id`.
|
450
|
+
MSG
|
451
|
+
end
|
452
|
+
|
453
|
+
relation = where(primary_key => id)
|
454
|
+
record = relation.take
|
455
|
+
|
456
|
+
raise_record_not_found_exception!(id, 0, 1) unless record
|
457
|
+
|
458
|
+
record
|
439
459
|
end
|
440
460
|
|
441
|
-
|
442
|
-
|
461
|
+
def find_some(ids)
|
462
|
+
return find_some_ordered(ids) unless order_values.present?
|
443
463
|
|
444
|
-
|
464
|
+
result = where(primary_key => ids).to_a
|
445
465
|
|
446
|
-
|
447
|
-
|
466
|
+
expected_size =
|
467
|
+
if limit_value && ids.size > limit_value
|
468
|
+
limit_value
|
469
|
+
else
|
470
|
+
ids.size
|
471
|
+
end
|
448
472
|
|
449
|
-
|
450
|
-
|
473
|
+
# 11 ids with limit 3, offset 9 should give 2 results.
|
474
|
+
if offset_value && (ids.size - offset_value < expected_size)
|
475
|
+
expected_size = ids.size - offset_value
|
476
|
+
end
|
451
477
|
|
452
|
-
|
453
|
-
|
454
|
-
limit_value
|
478
|
+
if result.size == expected_size
|
479
|
+
result
|
455
480
|
else
|
456
|
-
ids.size
|
481
|
+
raise_record_not_found_exception!(ids, result.size, expected_size)
|
457
482
|
end
|
483
|
+
end
|
484
|
+
|
485
|
+
def find_some_ordered(ids)
|
486
|
+
ids = ids.slice(offset_value || 0, limit_value || ids.size) || []
|
458
487
|
|
459
|
-
|
460
|
-
|
461
|
-
|
488
|
+
result = except(:limit, :offset).where(primary_key => ids).records
|
489
|
+
|
490
|
+
if result.size == ids.size
|
491
|
+
pk_type = @klass.type_for_attribute(primary_key)
|
492
|
+
|
493
|
+
records_by_id = result.index_by(&:id)
|
494
|
+
ids.map { |id| records_by_id.fetch(pk_type.cast(id)) }
|
495
|
+
else
|
496
|
+
raise_record_not_found_exception!(ids, result.size, ids.size)
|
497
|
+
end
|
462
498
|
end
|
463
499
|
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
500
|
+
def find_take
|
501
|
+
if loaded?
|
502
|
+
records.first
|
503
|
+
else
|
504
|
+
@take ||= limit(1).records.first
|
505
|
+
end
|
468
506
|
end
|
469
|
-
end
|
470
507
|
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
508
|
+
def find_take_with_limit(limit)
|
509
|
+
if loaded?
|
510
|
+
records.take(limit)
|
511
|
+
else
|
512
|
+
limit(limit).to_a
|
513
|
+
end
|
476
514
|
end
|
477
|
-
end
|
478
515
|
|
479
|
-
|
480
|
-
|
481
|
-
@records[index]
|
482
|
-
else
|
483
|
-
offset += index
|
484
|
-
@offsets[offset] ||= find_nth_with_limit(offset, 1).first
|
516
|
+
def find_nth(index)
|
517
|
+
@offsets[offset_index + index] ||= find_nth_with_limit(index, 1).first
|
485
518
|
end
|
486
|
-
end
|
487
519
|
|
488
|
-
|
489
|
-
|
490
|
-
|
520
|
+
def find_nth_with_limit(index, limit)
|
521
|
+
if loaded?
|
522
|
+
records[index, limit] || []
|
523
|
+
else
|
524
|
+
relation = ordered_relation
|
491
525
|
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
else
|
496
|
-
self
|
497
|
-
end
|
526
|
+
if limit_value
|
527
|
+
limit = [limit_value - index, limit].min
|
528
|
+
end
|
498
529
|
|
499
|
-
|
500
|
-
|
501
|
-
|
530
|
+
if limit > 0
|
531
|
+
relation = relation.offset(offset_index + index) unless index.zero?
|
532
|
+
relation.limit(limit).to_a
|
533
|
+
else
|
534
|
+
[]
|
535
|
+
end
|
536
|
+
end
|
537
|
+
end
|
502
538
|
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
539
|
+
def find_nth_from_last(index)
|
540
|
+
if loaded?
|
541
|
+
records[-index]
|
542
|
+
else
|
543
|
+
relation = ordered_relation
|
544
|
+
|
545
|
+
if equal?(relation) || has_limit_or_offset?
|
546
|
+
relation.records[-index]
|
510
547
|
else
|
511
|
-
|
548
|
+
relation.last(index)[-index]
|
512
549
|
end
|
550
|
+
end
|
551
|
+
end
|
552
|
+
|
553
|
+
def find_last(limit)
|
554
|
+
limit ? records.last(limit) : records.last
|
555
|
+
end
|
556
|
+
|
557
|
+
def ordered_relation
|
558
|
+
if order_values.empty? && primary_key
|
559
|
+
order(arel_attribute(primary_key).asc)
|
560
|
+
else
|
561
|
+
self
|
562
|
+
end
|
513
563
|
end
|
514
|
-
end
|
515
564
|
end
|
516
565
|
end
|