diff options
Diffstat (limited to 'activerecord/lib/active_record/relation/finder_methods.rb')
-rw-r--r-- | activerecord/lib/active_record/relation/finder_methods.rb | 103 |
1 files changed, 92 insertions, 11 deletions
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index d91d6367a3..01d46f7676 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -127,9 +127,9 @@ module ActiveRecord # def first(limit = nil) if limit - find_first_with_limit(limit) + find_nth_with_limit(offset_value, limit) else - find_first + find_nth(:first, offset_value) end end @@ -172,6 +172,86 @@ module ActiveRecord last or raise RecordNotFound end + # Find the second record. + # If no order is defined it will order by primary key. + # + # Person.second # returns the second object fetched by SELECT * FROM people + # Person.offset(3).second # returns the second object from OFFSET 3 (which is OFFSET 4) + # Person.where(["user_name = :u", { u: user_name }]).second + def second + find_nth(:second, offset_value ? offset_value + 1 : 1) + end + + # Same as +second+ but raises <tt>ActiveRecord::RecordNotFound</tt> if no record + # is found. + def second! + second or raise RecordNotFound + end + + # Find the third record. + # If no order is defined it will order by primary key. + # + # Person.third # returns the third object fetched by SELECT * FROM people + # Person.offset(3).third # returns the third object from OFFSET 3 (which is OFFSET 5) + # Person.where(["user_name = :u", { u: user_name }]).third + def third + find_nth(:third, offset_value ? offset_value + 2 : 2) + end + + # Same as +third+ but raises <tt>ActiveRecord::RecordNotFound</tt> if no record + # is found. + def third! + third or raise RecordNotFound + end + + # Find the fourth record. + # If no order is defined it will order by primary key. + # + # Person.fourth # returns the fourth object fetched by SELECT * FROM people + # Person.offset(3).fourth # returns the fourth object from OFFSET 3 (which is OFFSET 6) + # Person.where(["user_name = :u", { u: user_name }]).fourth + def fourth + find_nth(:fourth, offset_value ? offset_value + 3 : 3) + end + + # Same as +fourth+ but raises <tt>ActiveRecord::RecordNotFound</tt> if no record + # is found. + def fourth! + fourth or raise RecordNotFound + end + + # Find the fifth record. + # If no order is defined it will order by primary key. + # + # Person.fifth # returns the fifth object fetched by SELECT * FROM people + # Person.offset(3).fifth # returns the fifth object from OFFSET 3 (which is OFFSET 7) + # Person.where(["user_name = :u", { u: user_name }]).fifth + def fifth + find_nth(:fifth, offset_value ? offset_value + 4 : 4) + end + + # Same as +fifth+ but raises <tt>ActiveRecord::RecordNotFound</tt> if no record + # is found. + def fifth! + fifth or raise RecordNotFound + end + + # Find the forty-second record. Also known as accessing "the reddit". + # If no order is defined it will order by primary key. + # + # Person.forty_two # returns the forty-second object fetched by SELECT * FROM people + # Person.offset(3).forty_two # returns the fifth object from OFFSET 3 (which is OFFSET 44) + # Person.where(["user_name = :u", { u: user_name }]).forty_two + def forty_two + find_nth(:forty_two, offset_value ? offset_value + 41 : 41) + end + + # Same as +forty_two+ but raises <tt>ActiveRecord::RecordNotFound</tt> if no record + # is found. + def forty_two! + forty_two or raise RecordNotFound + end + # Returns +true+ if a record exists in the table that matches the +id+ or # conditions given, or +false+ otherwise. The argument can take six forms: # @@ -195,6 +275,7 @@ module ActiveRecord # Person.exists?(5) # Person.exists?('5') # Person.exists?(['name LIKE ?', "%#{query}%"]) + # Person.exists?(id: [1, 4, 8]) # Person.exists?(name: 'David') # Person.exists?(false) # Person.exists? @@ -230,9 +311,9 @@ module ActiveRecord conditions = " [#{conditions}]" if conditions if Array(ids).size == 1 - error = "Couldn't find #{@klass.name} with #{primary_key}=#{ids}#{conditions}" + error = "Couldn't find #{@klass.name} with '#{primary_key}'=#{ids}#{conditions}" else - error = "Couldn't find all #{@klass.name.pluralize} with IDs " + error = "Couldn't find all #{@klass.name.pluralize} with '#{primary_key}': " error << "(#{ids.join(", ")})#{conditions} (found #{result_size} results, but was looking for #{expected_size})" end @@ -363,19 +444,19 @@ module ActiveRecord end end - def find_first + def find_nth(ordinal, offset) if loaded? - @records.first + @records.send(ordinal) else - @first ||= find_first_with_limit(1).first + @offsets[offset] ||= find_nth_with_limit(offset, 1).first end end - def find_first_with_limit(limit) + def find_nth_with_limit(offset, limit) if order_values.empty? && primary_key - order(arel_table[primary_key].asc).limit(limit).to_a + order(arel_table[primary_key].asc).limit(limit).offset(offset).to_a else - limit(limit).to_a + limit(limit).offset(offset).to_a end end @@ -384,7 +465,7 @@ module ActiveRecord @records.last else @last ||= - if offset_value || limit_value + if limit_value to_a.last else reverse_order.limit(1).to_a.first |