From 0591c53efde948fd49a00aa23bdfc2ca26fca434 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 17 Apr 2005 17:16:24 +0000 Subject: Made the dynamic finders use the new find API and updated the examples here and there git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1196 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- activerecord/CHANGELOG | 2 ++ activerecord/lib/active_record/base.rb | 43 +++++++++++++++++------------ activerecord/test/deprecated_finder_test.rb | 9 ++++++ activerecord/test/finder_test.rb | 15 ++++++---- 4 files changed, 47 insertions(+), 22 deletions(-) (limited to 'activerecord') diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index ec31dd575f..108de3a8c8 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Fixed page caching for non-vhost applications living underneath the root #1004 [Ben Schumacher] + * Fixes a problem with the SQL Adapter which was resulting in IDENTITY_INSERT not being set to ON when it should be #1104 [adelle] * Added the option to specify the acceptance string in validates_acceptance_of #1106 [caleb@aei-tech.com] diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 1daed0e3a1..ee8d233d2c 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -55,7 +55,7 @@ module ActiveRecord #:nodoc: # Active Records accepts constructor parameters either in a hash or as a block. The hash method is especially useful when # you're receiving the data from somewhere else, like a HTTP request. It works like this: # - # user = User.new("name" => "David", "occupation" => "Code Artist") + # user = User.new(:name => "David", :occupation => "Code Artist") # user.name # => "David" # # You can also use block initialization: @@ -112,14 +112,17 @@ module ActiveRecord #:nodoc: # # Uses an integer of seconds to hold the length of the song # # def length=(minutes) - # write_attribute("length", minutes * 60) + # write_attribute(:length, minutes * 60) # end # # def length - # read_attribute("length") / 60 + # read_attribute(:length) / 60 # end # end # + # You can alternatively use self[:attribute]=(value) and self[:attribute] instead of write_attribute(:attribute, vaule) and + # read_attribute(:attribute) as a shorter form. + # # == Accessing attributes before they have been type casted # # Some times you want to be able to read the raw attribute data without having the column-determined type cast run its course first. @@ -134,16 +137,16 @@ module ActiveRecord #:nodoc: # # Dynamic attribute-based finders are a cleaner way of getting objects by simple queries without turning to SQL. They work by # appending the name of an attribute to find_by_, so you get finders like Person.find_by_user_name, Payment.find_by_transaction_id. - # So instead of writing Person.find_first(["user_name = ?", user_name]), you just do Person.find_by_user_name(user_name). + # So instead of writing Person.find(:first, ["user_name = ?", user_name]), you just do Person.find_by_user_name(user_name). # # It's also possible to use multiple attributes in the same find by separating them with "_and_", so you get finders like # Person.find_by_user_name_and_password or even Payment.find_by_purchaser_and_state_and_country. So instead of writing - # Person.find_first(["user_name = ? AND password = ?", user_name, password]), you just do + # Person.find(:first, ["user_name = ? AND password = ?", user_name, password]), you just do # Person.find_by_user_name_and_password(user_name, password). # - # It's even possible to use all the additional parameters to find_first and find_all. For example, the full interface for Payment.find_all_by_amount - # is actually Payment.find_all_by_amount(amount, orderings = nil, limit = nil, joins = nil). And the full interface to Person.find_by_user_name is - # actually Person.find_by_user_name(user_name, orderings = nil) + # It's even possible to use all the additional parameters to find. For example, the full interface for Payment.find_all_by_amount + # is actually Payment.find_all_by_amount(amount, options). And the full interface to Person.find_by_user_name is + # actually Person.find_by_user_name(user_name, options). So you could call Payment.find_all_by_amount(50, :order => "created_on"). # # == Saving arrays, hashes, and other non-mappable objects in text columns # @@ -154,7 +157,7 @@ module ActiveRecord #:nodoc: # serialize :preferences # end # - # user = User.create("preferences" => { "background" => "black", "display" => large }) + # user = User.create(:preferences) => { "background" => "black", "display" => large }) # User.find(user.id).preferences # => { "background" => "black", "display" => large } # # You can also specify an class option as the second parameter that'll raise an exception if a serialized object is retrieved as a @@ -164,7 +167,7 @@ module ActiveRecord #:nodoc: # serialize :preferences, Hash # end # - # user = User.create("preferences" => %w( one two three )) + # user = User.create(:preferences => %w( one two three )) # User.find(user.id).preferences # raises SerializationTypeMismatch # # == Single table inheritance @@ -177,8 +180,8 @@ module ActiveRecord #:nodoc: # class Client < Company; end # class PriorityClient < Client; end # - # When you do Firm.create("name" => "37signals"), this record will be saved in the companies table with type = "Firm". You can then - # fetch this row again using Company.find_first "name = '37signals'" and it will return a Firm object. + # When you do Firm.create(:name => "37signals"), this record will be saved in the companies table with type = "Firm". You can then + # fetch this row again using Company.find(:first, "name = '37signals'") and it will return a Firm object. # # If you don't have a type column defined in your table, single-table inheritance won't be triggered. In that case, it'll work just # like normal subclasses with no special magic for differentiating between them or reloading the right type with find. @@ -347,7 +350,7 @@ module ActiveRecord #:nodoc: # Example: # Person.exists?(5) def exists?(id) - !find_first("#{primary_key} = #{sanitize(id)}").nil? rescue false + !find(:first, :conditions => ["#{primary_key} = ?", id]).nil? rescue false end # Creates an object, instantly saves it as a record (if the validation permits it), and returns it. If the save @@ -751,18 +754,24 @@ module ActiveRecord #:nodoc: # find_first(["user_name = ?", user_name]) and find_first(["user_name = ? AND password = ?", user_name, password]) respectively. Also works # for find_all, but using find_all_by_amount(50) that are turned into find_all(["amount = ?", 50]). # - # It's even possible to use all the additional parameters to find_first and find_all. For example, the full interface for find_all_by_amount - # is actually find_all_by_amount(amount, orderings = nil, limit = nil, joins = nil). + # It's even possible to use all the additional parameters to find. For example, the full interface for find_all_by_amount + # is actually find_all_by_amount(amount, options). def method_missing(method_id, *arguments) method_name = method_id.id2name if method_name =~ /find_(all_by|by)_([_a-z][_a-z\d]*)/ - finder, attributes = ($1 == "all_by" ? :find_all : :find_first), $2.split("_and_") + finder, attributes = ($1 == "all_by" ? :all : :first), $2.split("_and_") attributes.each { |attr_name| super unless column_methods_hash[attr_name.intern] } attr_index = -1 conditions = attributes.collect { |attr_name| attr_index += 1; "#{attr_name} #{arguments[attr_index].nil? ? "IS" : "="} ? " }.join(" AND ") - send(finder, [conditions, *arguments[0...attributes.length]], *arguments[attributes.length..-1]) + + if arguments[attributes.length].is_a?(Hash) + find(finder, { :conditions => [conditions, *arguments[0...attributes.length]]}.merge(arguments[attributes.length])) + else + # deprecated API + send("find_#{finder}", [conditions, *arguments[0...attributes.length]], *arguments[attributes.length..-1]) + end else super end diff --git a/activerecord/test/deprecated_finder_test.rb b/activerecord/test/deprecated_finder_test.rb index c9bf7c7f43..422e17747d 100755 --- a/activerecord/test/deprecated_finder_test.rb +++ b/activerecord/test/deprecated_finder_test.rb @@ -127,6 +127,15 @@ class FinderTest < Test::Unit::TestCase assert_equal 'fixture_9', last_two_developers.first.name end + def test_find_all_by_one_attribute_with_options + topics = Topic.find_all_by_content("Have a nice day", nil, "id DESC") + assert @topics["first"].find, topics.last + + topics = Topic.find_all_by_content("Have a nice day", nil, "id DESC") + assert @topics["first"].find, topics.first + end + + protected def bind(statement, *vars) if vars.first.is_a?(Hash) diff --git a/activerecord/test/finder_test.rb b/activerecord/test/finder_test.rb index dd8e8b5487..0c672c2e35 100644 --- a/activerecord/test/finder_test.rb +++ b/activerecord/test/finder_test.rb @@ -202,6 +202,14 @@ class FinderTest < Test::Unit::TestCase assert_equal [], Topic.find_all_by_title("The First Topic!!") end + + def test_find_all_by_one_attribute_with_options + topics = Topic.find_all_by_content("Have a nice day", :order => "id DESC") + assert @topics["first"].find, topics.last + + topics = Topic.find_all_by_content("Have a nice day", :order => "id") + assert @topics["first"].find, topics.first + end def test_find_all_by_boolean_attribute topics = Topic.find_all_by_approved(false) @@ -241,16 +249,13 @@ class FinderTest < Test::Unit::TestCase end def test_find_all_with_limit - first_five_developers = Developer.find_all nil, 'id ASC', 5 + first_five_developers = Developer.find :all, :order => 'id ASC', :limit => 5 assert_equal 5, first_five_developers.length assert_equal 'David', first_five_developers.first.name assert_equal 'fixture_5', first_five_developers.last.name - no_developers = Developer.find_all nil, 'id ASC', 0 + no_developers = Developer.find :all, :order => 'id ASC', :limit => 0 assert_equal 0, no_developers.length - - assert_equal first_five_developers, Developer.find_all(nil, 'id ASC', [5]) - assert_equal no_developers, Developer.find_all(nil, 'id ASC', [0]) end def test_find_all_with_limit_and_offset -- cgit v1.2.3