activerecord 4.2.0 → 5.2.8.1
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 +640 -928
- 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 +264 -247
- data/lib/active_record/association_relation.rb +24 -6
- data/lib/active_record/associations/alias_tracker.rb +29 -35
- data/lib/active_record/associations/association.rb +87 -41
- data/lib/active_record/associations/association_scope.rb +106 -132
- data/lib/active_record/associations/belongs_to_association.rb +55 -36
- 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 +14 -23
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +50 -39
- 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 +145 -266
- data/lib/active_record/associations/collection_proxy.rb +242 -138
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +35 -75
- data/lib/active_record/associations/has_many_through_association.rb +51 -69
- data/lib/active_record/associations/has_one_association.rb +39 -24
- data/lib/active_record/associations/has_one_through_association.rb +18 -9
- data/lib/active_record/associations/join_dependency/join_association.rb +40 -81
- 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 +134 -154
- data/lib/active_record/associations/preloader/association.rb +85 -116
- data/lib/active_record/associations/preloader/through_association.rb +85 -74
- data/lib/active_record/associations/preloader.rb +83 -93
- data/lib/active_record/associations/singular_association.rb +27 -40
- data/lib/active_record/associations/through_association.rb +48 -23
- data/lib/active_record/associations.rb +1732 -1596
- 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 +12 -5
- data/lib/active_record/attribute_methods/dirty.rb +94 -125
- 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 +62 -36
- data/lib/active_record/attribute_methods/write.rb +31 -46
- data/lib/active_record/attribute_methods.rb +170 -117
- data/lib/active_record/attributes.rb +201 -74
- data/lib/active_record/autosave_association.rb +118 -45
- data/lib/active_record/base.rb +60 -48
- 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 +37 -13
- data/lib/active_record/collection_cache_key.rb +53 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +712 -284
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +10 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +254 -87
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +72 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -52
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +6 -4
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +67 -46
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +328 -217
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +81 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +617 -212
- data/lib/active_record/connection_adapters/abstract/transaction.rb +139 -75
- data/lib/active_record/connection_adapters/abstract_adapter.rb +332 -191
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +567 -563
- 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 +42 -195
- data/lib/active_record/connection_adapters/postgresql/column.rb +35 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -115
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -57
- 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 +5 -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 -13
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +7 -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 +7 -9
- 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 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +65 -51
- 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 +466 -280
- 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 +439 -330
- 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 -324
- 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 +205 -202
- data/lib/active_record/counter_cache.rb +80 -37
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -105
- data/lib/active_record/enum.rb +136 -90
- data/lib/active_record/errors.rb +180 -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 +11 -6
- data/lib/active_record/fixture_set/file.rb +35 -9
- data/lib/active_record/fixtures.rb +193 -135
- 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 +48 -0
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +92 -98
- 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 +594 -267
- data/lib/active_record/model_schema.rb +292 -111
- data/lib/active_record/nested_attributes.rb +266 -214
- data/lib/active_record/no_touching.rb +8 -2
- data/lib/active_record/null_relation.rb +24 -37
- data/lib/active_record/persistence.rb +350 -119
- data/lib/active_record/query_cache.rb +13 -24
- data/lib/active_record/querying.rb +19 -17
- data/lib/active_record/railtie.rb +117 -35
- 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 +160 -174
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +447 -288
- 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 +259 -244
- data/lib/active_record/relation/delegation.rb +67 -60
- data/lib/active_record/relation/finder_methods.rb +290 -253
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +91 -68
- data/lib/active_record/relation/predicate_builder/array_handler.rb +24 -23
- 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 +118 -92
- data/lib/active_record/relation/query_attribute.rb +45 -0
- data/lib/active_record/relation/query_methods.rb +446 -389
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +18 -16
- 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 -339
- 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 -19
- data/lib/active_record/scoping/default.rb +102 -84
- 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 +136 -95
- data/lib/active_record/tasks/mysql_database_tasks.rb +59 -89
- data/lib/active_record/tasks/postgresql_database_tasks.rb +84 -31
- 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 +208 -123
- 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 -41
- data/lib/active_record/type/date_time.rb +4 -38
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +13 -5
- 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 +30 -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 +41 -32
- data/lib/active_record/validations.rb +38 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +36 -21
- 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 -6
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +8 -7
- 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.rb +7 -5
- metadata +77 -53
- 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 -149
- data/lib/active_record/attribute_set/builder.rb +0 -86
- data/lib/active_record/attribute_set.rb +0 -77
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- 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 -30
- data/lib/active_record/type/decimal.rb +0 -40
- 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 -55
- 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 -36
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -101
- /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -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,48 +100,36 @@ 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).
|
115
113
|
# If no order is defined it will order by primary key.
|
116
114
|
#
|
117
|
-
# Person.first # returns the first object fetched by SELECT * FROM people
|
115
|
+
# Person.first # returns the first object fetched by SELECT * FROM people ORDER BY people.id LIMIT 1
|
118
116
|
# Person.where(["user_name = ?", user_name]).first
|
119
117
|
# Person.where(["user_name = :u", { u: user_name }]).first
|
120
118
|
# Person.order("created_on DESC").offset(5).first
|
121
|
-
# Person.first(3) # returns the first three objects fetched by SELECT * FROM people LIMIT 3
|
122
|
-
#
|
123
|
-
# ==== Rails 3
|
124
|
-
#
|
125
|
-
# Person.first # SELECT "people".* FROM "people" LIMIT 1
|
126
|
-
#
|
127
|
-
# NOTE: Rails 3 may not order this query by the primary key and the order
|
128
|
-
# will depend on the database implementation. In order to ensure that behavior,
|
129
|
-
# use <tt>User.order(:id).first</tt> instead.
|
130
|
-
#
|
131
|
-
# ==== Rails 4
|
132
|
-
#
|
133
|
-
# Person.first # SELECT "people".* FROM "people" ORDER BY "people"."id" ASC LIMIT 1
|
119
|
+
# Person.first(3) # returns the first three objects fetched by SELECT * FROM people ORDER BY people.id LIMIT 3
|
134
120
|
#
|
135
121
|
def first(limit = nil)
|
136
122
|
if limit
|
137
|
-
find_nth_with_limit(
|
123
|
+
find_nth_with_limit(0, limit)
|
138
124
|
else
|
139
|
-
find_nth
|
125
|
+
find_nth 0
|
140
126
|
end
|
141
127
|
end
|
142
128
|
|
143
|
-
# Same as
|
144
|
-
# is found. Note that
|
129
|
+
# Same as #first but raises ActiveRecord::RecordNotFound if no record
|
130
|
+
# is found. Note that #first! accepts no arguments.
|
145
131
|
def first!
|
146
|
-
|
132
|
+
first || raise_record_not_found_exception!
|
147
133
|
end
|
148
134
|
|
149
135
|
# Find the last record (or last N records if a parameter is supplied).
|
@@ -162,21 +148,18 @@ module ActiveRecord
|
|
162
148
|
#
|
163
149
|
# [#<Person id:4>, #<Person id:3>, #<Person id:2>]
|
164
150
|
def last(limit = nil)
|
165
|
-
if
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
else
|
172
|
-
find_last
|
173
|
-
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
|
174
157
|
end
|
175
158
|
|
176
|
-
# Same as
|
177
|
-
# is found. Note that
|
159
|
+
# Same as #last but raises ActiveRecord::RecordNotFound if no record
|
160
|
+
# is found. Note that #last! accepts no arguments.
|
178
161
|
def last!
|
179
|
-
last
|
162
|
+
last || raise_record_not_found_exception!
|
180
163
|
end
|
181
164
|
|
182
165
|
# Find the second record.
|
@@ -186,13 +169,13 @@ module ActiveRecord
|
|
186
169
|
# Person.offset(3).second # returns the second object from OFFSET 3 (which is OFFSET 4)
|
187
170
|
# Person.where(["user_name = :u", { u: user_name }]).second
|
188
171
|
def second
|
189
|
-
find_nth
|
172
|
+
find_nth 1
|
190
173
|
end
|
191
174
|
|
192
|
-
# Same as
|
175
|
+
# Same as #second but raises ActiveRecord::RecordNotFound if no record
|
193
176
|
# is found.
|
194
177
|
def second!
|
195
|
-
|
178
|
+
second || raise_record_not_found_exception!
|
196
179
|
end
|
197
180
|
|
198
181
|
# Find the third record.
|
@@ -202,13 +185,13 @@ module ActiveRecord
|
|
202
185
|
# Person.offset(3).third # returns the third object from OFFSET 3 (which is OFFSET 5)
|
203
186
|
# Person.where(["user_name = :u", { u: user_name }]).third
|
204
187
|
def third
|
205
|
-
find_nth
|
188
|
+
find_nth 2
|
206
189
|
end
|
207
190
|
|
208
|
-
# Same as
|
191
|
+
# Same as #third but raises ActiveRecord::RecordNotFound if no record
|
209
192
|
# is found.
|
210
193
|
def third!
|
211
|
-
|
194
|
+
third || raise_record_not_found_exception!
|
212
195
|
end
|
213
196
|
|
214
197
|
# Find the fourth record.
|
@@ -218,13 +201,13 @@ module ActiveRecord
|
|
218
201
|
# Person.offset(3).fourth # returns the fourth object from OFFSET 3 (which is OFFSET 6)
|
219
202
|
# Person.where(["user_name = :u", { u: user_name }]).fourth
|
220
203
|
def fourth
|
221
|
-
find_nth
|
204
|
+
find_nth 3
|
222
205
|
end
|
223
206
|
|
224
|
-
# Same as
|
207
|
+
# Same as #fourth but raises ActiveRecord::RecordNotFound if no record
|
225
208
|
# is found.
|
226
209
|
def fourth!
|
227
|
-
|
210
|
+
fourth || raise_record_not_found_exception!
|
228
211
|
end
|
229
212
|
|
230
213
|
# Find the fifth record.
|
@@ -234,13 +217,13 @@ module ActiveRecord
|
|
234
217
|
# Person.offset(3).fifth # returns the fifth object from OFFSET 3 (which is OFFSET 7)
|
235
218
|
# Person.where(["user_name = :u", { u: user_name }]).fifth
|
236
219
|
def fifth
|
237
|
-
find_nth
|
220
|
+
find_nth 4
|
238
221
|
end
|
239
222
|
|
240
|
-
# Same as
|
223
|
+
# Same as #fifth but raises ActiveRecord::RecordNotFound if no record
|
241
224
|
# is found.
|
242
225
|
def fifth!
|
243
|
-
|
226
|
+
fifth || raise_record_not_found_exception!
|
244
227
|
end
|
245
228
|
|
246
229
|
# Find the forty-second record. Also known as accessing "the reddit".
|
@@ -250,17 +233,49 @@ module ActiveRecord
|
|
250
233
|
# Person.offset(3).forty_two # returns the forty-second object from OFFSET 3 (which is OFFSET 44)
|
251
234
|
# Person.where(["user_name = :u", { u: user_name }]).forty_two
|
252
235
|
def forty_two
|
253
|
-
find_nth
|
236
|
+
find_nth 41
|
254
237
|
end
|
255
238
|
|
256
|
-
# Same as
|
239
|
+
# Same as #forty_two but raises ActiveRecord::RecordNotFound if no record
|
257
240
|
# is found.
|
258
241
|
def forty_two!
|
259
|
-
|
242
|
+
forty_two || raise_record_not_found_exception!
|
243
|
+
end
|
244
|
+
|
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!
|
260
259
|
end
|
261
260
|
|
262
|
-
#
|
263
|
-
#
|
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:
|
264
279
|
#
|
265
280
|
# * Integer - Finds the record with this primary key.
|
266
281
|
# * String - Finds the record with a primary key corresponding to this
|
@@ -270,10 +285,10 @@ module ActiveRecord
|
|
270
285
|
# * Hash - Finds the record that matches these +find+-style conditions
|
271
286
|
# (such as <tt>{name: 'David'}</tt>).
|
272
287
|
# * +false+ - Returns always +false+.
|
273
|
-
# * No args - Returns +false+ if the
|
288
|
+
# * No args - Returns +false+ if the relation is empty, +true+ otherwise.
|
274
289
|
#
|
275
290
|
# For more information about specifying conditions as a hash or array,
|
276
|
-
# see the Conditions section in the introduction to
|
291
|
+
# see the Conditions section in the introduction to ActiveRecord::Base.
|
277
292
|
#
|
278
293
|
# Note: You can't pass in a condition as a string (like <tt>name =
|
279
294
|
# 'Jamie'</tt>), since it would be sanitized and then queried against
|
@@ -286,243 +301,265 @@ module ActiveRecord
|
|
286
301
|
# Person.exists?(name: 'David')
|
287
302
|
# Person.exists?(false)
|
288
303
|
# Person.exists?
|
304
|
+
# Person.where(name: 'Spartacus', rating: 4).exists?
|
289
305
|
def exists?(conditions = :none)
|
290
306
|
if Base === conditions
|
291
|
-
|
292
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
307
|
+
raise ArgumentError, <<-MSG.squish
|
293
308
|
You are passing an instance of ActiveRecord::Base to `exists?`.
|
294
|
-
Please pass the id of the object by calling `.id
|
309
|
+
Please pass the id of the object by calling `.id`.
|
295
310
|
MSG
|
296
311
|
end
|
297
312
|
|
298
|
-
return false if !conditions
|
299
|
-
|
300
|
-
relation = apply_join_dependency(self, construct_join_dependency)
|
301
|
-
return false if ActiveRecord::NullRelation === relation
|
302
|
-
|
303
|
-
relation = relation.except(:select, :order).select(ONE_AS_ONE).limit(1)
|
313
|
+
return false if !conditions || limit_value == 0
|
304
314
|
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
else
|
309
|
-
unless conditions == :none
|
310
|
-
relation = where(primary_key => conditions)
|
311
|
-
end
|
315
|
+
if eager_loading?
|
316
|
+
relation = apply_join_dependency(eager_loading: false)
|
317
|
+
return relation.exists?(conditions)
|
312
318
|
end
|
313
319
|
|
314
|
-
|
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
|
315
325
|
end
|
316
326
|
|
317
327
|
# This method is called whenever no records are found with either a single
|
318
|
-
# id or multiple ids and raises
|
328
|
+
# id or multiple ids and raises an ActiveRecord::RecordNotFound exception.
|
319
329
|
#
|
320
330
|
# The error message is different depending on whether a single id or
|
321
331
|
# multiple ids are provided. If multiple ids are provided, then the number
|
322
332
|
# of results obtained should be provided in the +result_size+ argument and
|
323
333
|
# the expected number of results should be provided in the +expected_size+
|
324
334
|
# argument.
|
325
|
-
def raise_record_not_found_exception!(ids, result_size, expected_size)
|
326
|
-
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)
|
327
337
|
conditions = " [#{conditions}]" if conditions
|
328
|
-
|
329
|
-
|
330
|
-
|
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)
|
331
347
|
else
|
332
|
-
error = "Couldn't find all #{
|
333
|
-
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)
|
334
352
|
end
|
335
|
-
|
336
|
-
raise RecordNotFound, error
|
337
353
|
end
|
338
354
|
|
339
355
|
private
|
340
356
|
|
341
|
-
|
342
|
-
|
343
|
-
|
357
|
+
def offset_index
|
358
|
+
offset_value || 0
|
359
|
+
end
|
344
360
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
#
|
349
|
-
# failing to do so means that in cases like activerecord/test/cases/associations/inner_join_association_test.rb:136
|
350
|
-
# incorrect SQL is generated. In that case, the join dependency for
|
351
|
-
# SpecialCategorizations is constructed without knowledge of the
|
352
|
-
# preexisting join in joins_values to categorizations (by way of
|
353
|
-
# the `has_many :through` for categories).
|
354
|
-
#
|
355
|
-
join_dependency = construct_join_dependency(joins_values)
|
356
|
-
|
357
|
-
aliases = join_dependency.aliases
|
358
|
-
relation = select aliases.columns
|
359
|
-
relation = apply_join_dependency(relation, join_dependency)
|
360
|
-
|
361
|
-
if block_given?
|
362
|
-
yield relation
|
363
|
-
else
|
364
|
-
if ActiveRecord::NullRelation === relation
|
365
|
-
[]
|
361
|
+
def construct_relation_for_exists(conditions)
|
362
|
+
if distinct_value && offset_value
|
363
|
+
relation = except(:order).limit!(1)
|
366
364
|
else
|
367
|
-
|
368
|
-
rows = connection.select_all(arel, 'SQL', arel.bind_values + relation.bind_values)
|
369
|
-
join_dependency.instantiate(rows, aliases)
|
365
|
+
relation = except(:select, :distinct, :order)._select!(ONE_AS_ONE).limit!(1)
|
370
366
|
end
|
371
|
-
end
|
372
|
-
end
|
373
367
|
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
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
|
378
374
|
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
apply_join_dependency(self, construct_join_dependency(from))
|
375
|
+
relation
|
376
|
+
end
|
377
|
+
|
378
|
+
def construct_join_dependency
|
379
|
+
including = eager_load_values + includes_values
|
380
|
+
ActiveRecord::Associations::JoinDependency.new(
|
381
|
+
klass, table, including
|
382
|
+
)
|
388
383
|
end
|
389
|
-
end
|
390
384
|
|
391
|
-
|
392
|
-
|
393
|
-
|
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)
|
394
388
|
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
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
|
401
401
|
end
|
402
|
-
relation.except(:limit, :offset)
|
403
402
|
end
|
404
|
-
end
|
405
403
|
|
406
|
-
|
407
|
-
|
408
|
-
|
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
|
+
)
|
409
409
|
|
410
|
-
|
411
|
-
arel = relation.arel
|
410
|
+
relation = relation.except(:select).select(values).distinct!
|
412
411
|
|
413
|
-
|
414
|
-
|
415
|
-
|
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
|
416
415
|
|
417
|
-
|
418
|
-
|
419
|
-
|
416
|
+
def using_limitable_reflections?(reflections)
|
417
|
+
reflections.none?(&:collection?)
|
418
|
+
end
|
420
419
|
|
421
|
-
|
420
|
+
def find_with_ids(*ids)
|
421
|
+
raise UnknownPrimaryKey.new(@klass) if primary_key.nil?
|
422
422
|
|
423
|
-
|
424
|
-
|
423
|
+
expects_array = ids.first.kind_of?(Array)
|
424
|
+
return [] if expects_array && ids.first.empty?
|
425
425
|
|
426
|
-
|
427
|
-
return ids.first if expects_array && ids.first.empty?
|
426
|
+
ids = ids.flatten.compact.uniq
|
428
427
|
|
429
|
-
|
428
|
+
model_name = @klass.name
|
430
429
|
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
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)
|
439
443
|
end
|
440
|
-
rescue RangeError
|
441
|
-
raise RecordNotFound, "Couldn't find #{@klass.name} with an out of range ID"
|
442
|
-
end
|
443
444
|
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
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
|
451
459
|
end
|
452
460
|
|
453
|
-
|
454
|
-
|
461
|
+
def find_some(ids)
|
462
|
+
return find_some_ordered(ids) unless order_values.present?
|
455
463
|
|
456
|
-
|
464
|
+
result = where(primary_key => ids).to_a
|
457
465
|
|
458
|
-
|
459
|
-
|
466
|
+
expected_size =
|
467
|
+
if limit_value && ids.size > limit_value
|
468
|
+
limit_value
|
469
|
+
else
|
470
|
+
ids.size
|
471
|
+
end
|
460
472
|
|
461
|
-
|
462
|
-
|
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
|
463
477
|
|
464
|
-
|
465
|
-
|
466
|
-
limit_value
|
478
|
+
if result.size == expected_size
|
479
|
+
result
|
467
480
|
else
|
468
|
-
ids.size
|
481
|
+
raise_record_not_found_exception!(ids, result.size, expected_size)
|
469
482
|
end
|
483
|
+
end
|
484
|
+
|
485
|
+
def find_some_ordered(ids)
|
486
|
+
ids = ids.slice(offset_value || 0, limit_value || ids.size) || []
|
487
|
+
|
488
|
+
result = except(:limit, :offset).where(primary_key => ids).records
|
470
489
|
|
471
|
-
|
472
|
-
|
473
|
-
|
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
|
474
498
|
end
|
475
499
|
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
500
|
+
def find_take
|
501
|
+
if loaded?
|
502
|
+
records.first
|
503
|
+
else
|
504
|
+
@take ||= limit(1).records.first
|
505
|
+
end
|
480
506
|
end
|
481
|
-
end
|
482
507
|
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
508
|
+
def find_take_with_limit(limit)
|
509
|
+
if loaded?
|
510
|
+
records.take(limit)
|
511
|
+
else
|
512
|
+
limit(limit).to_a
|
513
|
+
end
|
488
514
|
end
|
489
|
-
end
|
490
515
|
|
491
|
-
|
492
|
-
|
493
|
-
@records[index]
|
494
|
-
else
|
495
|
-
offset += index
|
496
|
-
@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
|
497
518
|
end
|
498
|
-
end
|
499
519
|
|
500
|
-
|
501
|
-
|
502
|
-
|
520
|
+
def find_nth_with_limit(index, limit)
|
521
|
+
if loaded?
|
522
|
+
records[index, limit] || []
|
523
|
+
else
|
524
|
+
relation = ordered_relation
|
503
525
|
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
else
|
508
|
-
self
|
509
|
-
end
|
526
|
+
if limit_value
|
527
|
+
limit = [limit_value - index, limit].min
|
528
|
+
end
|
510
529
|
|
511
|
-
|
512
|
-
|
513
|
-
|
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
|
514
538
|
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
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]
|
522
547
|
else
|
523
|
-
|
548
|
+
relation.last(index)[-index]
|
524
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
|
525
563
|
end
|
526
|
-
end
|
527
564
|
end
|
528
565
|
end
|