diff --git a/lib/active_hash/relation.rb b/lib/active_hash/relation.rb index 428a0400..0700c4d5 100644 --- a/lib/active_hash/relation.rb +++ b/lib/active_hash/relation.rb @@ -12,6 +12,7 @@ def initialize(klass, all_records, query_hash = nil) self.all_records = all_records self.query_hash = query_hash self.records_dirty = false + self.order_values = [] self end @@ -75,7 +76,14 @@ def pick(*column_names) end def reload - @records = filter_all_records_by_query_hash + filtered_records = filter_all_records_by_query_hash + + if order_values.present? + filtered_records = filtered_records.dup if filtered_records.equal? all_records + order_by_args!(filtered_records) + end + + @records = filtered_records end def order(*options) @@ -83,10 +91,8 @@ def order(*options) relation = where({}) return relation if options.blank? - processed_args = preprocess_order_args(options) candidates = relation.dup - - order_by_args!(candidates, processed_args) + candidates.order_values.concat preprocess_order_args(options) candidates end @@ -95,12 +101,11 @@ def to_ary records.dup end - - attr_reader :query_hash, :klass, :all_records, :records_dirty + attr_reader :query_hash, :klass, :all_records, :records_dirty, :order_values private - attr_writer :query_hash, :klass, :all_records, :records_dirty + attr_writer :query_hash, :klass, :all_records, :records_dirty, :order_values def records if @records.nil? || records_dirty @@ -164,8 +169,8 @@ def preprocess_order_args(order_args) ary.map! { |e| e.split(/\W+/) }.reverse! end - def order_by_args!(candidates, args) - args.each do |arg| + def order_by_args!(candidates) + order_values.each do |arg| field, dir = if arg.is_a?(Hash) arg.to_a.flatten.map(&:to_sym) elsif arg.is_a?(Array) diff --git a/spec/active_hash/base_spec.rb b/spec/active_hash/base_spec.rb index 7935eec0..59453dfc 100644 --- a/spec/active_hash/base_spec.rb +++ b/spec/active_hash/base_spec.rb @@ -957,6 +957,17 @@ class Region < ActiveHash::Base expect(countries.first).to eq Country.find_by(name: "Canada") expect(countries.second).to eq Country.find_by(name: "US") end + + it "doesn't break the order of original records" do + countries = Country.order(id: :desc) + expect(countries.first).to eq Country.find_by(name: "Mexico") + expect(countries.second).to eq Country.find_by(name: "Canada") + expect(countries.third).to eq Country.find_by(name: "US") + + expect(Country.all.first).to eq Country.find_by(name: "US") + expect(Country.all.second).to eq Country.find_by(name: "Canada") + expect(Country.all.third).to eq Country.find_by(name: "Mexico") + end end describe "#method_missing" do