aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--[-rwxr-xr-x]activerecord/lib/active_record/base.rb1
-rw-r--r--activerecord/lib/active_record/dynamic_finder_match.rb3
-rw-r--r--activerecord/test/cases/finder_test.rb40
3 files changed, 39 insertions, 5 deletions
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 907495a416..0fe9e12549 100755..100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -287,6 +287,7 @@ module ActiveRecord #:nodoc:
# It's even possible to use all the additional parameters to find. For example, the full interface for <tt>Payment.find_all_by_amount</tt>
# is actually <tt>Payment.find_all_by_amount(amount, options)</tt>. And the full interface to <tt>Person.find_by_user_name</tt> is
# actually <tt>Person.find_by_user_name(user_name, options)</tt>. So you could call <tt>Payment.find_all_by_amount(50, :order => "created_on")</tt>.
+ # Also you may call <tt>Payment.find_last_by_amount(amount, options)</tt> returning the last record matching that amount and options.
#
# The same dynamic finder style can be used to create the object if it doesn't already exist. This dynamic finder is called with
# <tt>find_or_create_by_</tt> and will return the object if it already exists and otherwise creates it, then returns it. Protected attributes won't be set unless they are given in a block. For example:
diff --git a/activerecord/lib/active_record/dynamic_finder_match.rb b/activerecord/lib/active_record/dynamic_finder_match.rb
index b105b919f5..f4a5712981 100644
--- a/activerecord/lib/active_record/dynamic_finder_match.rb
+++ b/activerecord/lib/active_record/dynamic_finder_match.rb
@@ -8,7 +8,8 @@ module ActiveRecord
def initialize(method)
@finder = :find_initial
case method.to_s
- when /^find_(all_by|by)_([_a-zA-Z]\w*)$/
+ when /^find_(all_by|last_by|by)_([_a-zA-Z]\w*)$/
+ @finder = :find_last if $1 == 'last_by'
@finder = :find_every if $1 == 'all_by'
names = $2
when /^find_by_([_a-zA-Z]\w*)\!$/
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index 2ce49ed76f..3eee2056dd 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -197,11 +197,11 @@ class FinderTest < ActiveRecord::TestCase
first = Topic.find(:first, :conditions => "title = 'The First Topic!'")
assert_nil(first)
end
-
+
def test_first
assert_equal topics(:second).title, Topic.first(:conditions => "title = 'The Second Topic of the day'").title
end
-
+
def test_first_failing
assert_nil Topic.first(:conditions => "title = 'The Second Topic of the day!'")
end
@@ -418,7 +418,7 @@ class FinderTest < ActiveRecord::TestCase
def test_named_bind_variables
assert_equal '1', bind(':a', :a => 1) # ' ruby-mode
assert_equal '1 1', bind(':a :a', :a => 1) # ' ruby-mode
-
+
assert_nothing_raised { bind("'+00:00'", :foo => "bar") }
assert_kind_of Firm, Company.find(:first, :conditions => ["name = :name", { :name => "37signals" }])
@@ -589,6 +589,38 @@ class FinderTest < ActiveRecord::TestCase
assert_nil Topic.find_by_title_and_author_name("The First Topic", "Mary")
end
+ def test_find_last_by_one_attribute
+ assert_equal Topic.last, Topic.find_last_by_title(Topic.last.title)
+ assert_nil Topic.find_last_by_title("A title with no matches")
+ end
+
+ def test_find_last_by_one_attribute_caches_dynamic_finder
+ # ensure this test can run independently of order
+ class << Topic; self; end.send(:remove_method, :find_last_by_title) if Topic.public_methods.any? { |m| m.to_s == 'find_last_by_title' }
+ assert !Topic.public_methods.any? { |m| m.to_s == 'find_last_by_title' }
+ t = Topic.find_last_by_title(Topic.last)
+ assert Topic.public_methods.any? { |m| m.to_s == 'find_last_by_title' }
+ end
+
+ def test_find_last_by_invalid_method_syntax
+ assert_raises(NoMethodError) { Topic.fail_to_find_last_by_title("The First Topic") }
+ assert_raises(NoMethodError) { Topic.find_last_by_title?("The First Topic") }
+ end
+
+ def test_find_last_by_one_attribute_with_several_options
+ assert_equal accounts(:signals37), Account.find_last_by_credit_limit(50, :order => 'id DESC', :conditions => ['id != ?', 3])
+ end
+
+ def test_find_last_by_one_missing_attribute
+ assert_raises(NoMethodError) { Topic.find_last_by_undertitle("The Last Topic!") }
+ end
+
+ def test_find_last_by_two_attributes
+ topic = Topic.last
+ assert_equal topic, Topic.find_last_by_title_and_author_name(topic.title, topic.author_name)
+ assert_nil Topic.find_last_by_title_and_author_name(topic.title, "Anonymous")
+ end
+
def test_find_all_by_one_attribute
topics = Topic.find_all_by_content("Have a nice day")
assert_equal 2, topics.size
@@ -782,7 +814,7 @@ class FinderTest < ActiveRecord::TestCase
assert c.valid?
assert !c.new_record?
end
-
+
def test_dynamic_find_or_initialize_from_one_attribute_caches_method
class << Company; self; end.send(:remove_method, :find_or_initialize_by_name) if Company.public_methods.any? { |m| m.to_s == 'find_or_initialize_by_name' }
assert !Company.public_methods.any? { |m| m.to_s == 'find_or_initialize_by_name' }