diff options
author | Tekin Suleyman <tekin@tekin.co.uk> | 2018-11-17 13:50:01 -0800 |
---|---|---|
committer | Tekin Suleyman <tekin@tekin.co.uk> | 2018-11-26 16:19:52 -0800 |
commit | 3b9982a3b778b63488975eb03592d33aa9fb04dd (patch) | |
tree | 1c738d8c2e7b47ed20fe0937b8a723b6eb1ae310 /activerecord/lib | |
parent | 85b080365313437f646070ca214fef433c06db6a (diff) | |
download | rails-3b9982a3b778b63488975eb03592d33aa9fb04dd.tar.gz rails-3b9982a3b778b63488975eb03592d33aa9fb04dd.tar.bz2 rails-3b9982a3b778b63488975eb03592d33aa9fb04dd.zip |
Make implicit order column configurable
When calling ordered finder methods such as +first+ or +last+ without an
explicit order clause, ActiveRecord sorts records by primary key. This
can result in unpredictable and surprising behaviour when the primary
key is not an auto-incrementing integer, for example when it's a UUID.
This change makes it possible to override the column used for implicit
ordering such that +first+ and +last+ will return more predictable
results. For Example:
class Project < ActiveRecord::Base
self.implicit_order_column = "created_at"
end
Diffstat (limited to 'activerecord/lib')
-rw-r--r-- | activerecord/lib/active_record/model_schema.rb | 16 | ||||
-rw-r--r-- | activerecord/lib/active_record/relation/finder_methods.rb | 4 |
2 files changed, 18 insertions, 2 deletions
diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb index c50a420432..55fc58e339 100644 --- a/activerecord/lib/active_record/model_schema.rb +++ b/activerecord/lib/active_record/model_schema.rb @@ -102,6 +102,21 @@ module ActiveRecord # If true, the default table name for a Product class will be "products". If false, it would just be "product". # See table_name for the full rules on table/class naming. This is true, by default. + ## + # :singleton-method: implicit_order_column + # :call-seq: implicit_order_column + # + # The name of the column records are ordered by if no explicit order clause + # is used during an ordered finder call. If not set the primary key is used. + + ## + # :singleton-method: implicit_order_column= + # :call-seq: implicit_order_column=(column_name) + # + # Sets the column to sort records by when no explicit order clause is used + # during an ordered finder call. Useful when the primary key is not an + # auto-incrementing integer, for example when it's a UUID. Note that using + # a non-unique column can result in non-deterministic results. included do mattr_accessor :primary_key_prefix_type, instance_writer: false @@ -110,6 +125,7 @@ module ActiveRecord class_attribute :schema_migrations_table_name, instance_accessor: false, default: "schema_migrations" class_attribute :internal_metadata_table_name, instance_accessor: false, default: "ar_internal_metadata" class_attribute :pluralize_table_names, instance_writer: false, default: true + class_attribute :implicit_order_column, instance_accessor: false self.protected_environments = ["production"] self.inheritance_column = "type" diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index afaa900442..dc03b196f4 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -550,8 +550,8 @@ module ActiveRecord end def ordered_relation - if order_values.empty? && primary_key - order(arel_attribute(primary_key).asc) + if order_values.empty? && (implicit_order_column || primary_key) + order(arel_attribute(implicit_order_column || primary_key).asc) else self end |