mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
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
This commit is contained in:
parent
806cf6d76a
commit
0591c53efd
4 changed files with 47 additions and 22 deletions
|
@ -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]
|
||||
|
|
|
@ -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 <tt>find_by_</tt>, so you get finders like <tt>Person.find_by_user_name, Payment.find_by_transaction_id</tt>.
|
||||
# So instead of writing <tt>Person.find_first(["user_name = ?", user_name])</tt>, you just do <tt>Person.find_by_user_name(user_name)</tt>.
|
||||
# So instead of writing <tt>Person.find(:first, ["user_name = ?", user_name])</tt>, you just do <tt>Person.find_by_user_name(user_name)</tt>.
|
||||
#
|
||||
# It's also possible to use multiple attributes in the same find by separating them with "_and_", so you get finders like
|
||||
# <tt>Person.find_by_user_name_and_password</tt> or even <tt>Payment.find_by_purchaser_and_state_and_country</tt>. So instead of writing
|
||||
# <tt>Person.find_first(["user_name = ? AND password = ?", user_name, password])</tt>, you just do
|
||||
# <tt>Person.find(:first, ["user_name = ? AND password = ?", user_name, password])</tt>, you just do
|
||||
# <tt>Person.find_by_user_name_and_password(user_name, password)</tt>.
|
||||
#
|
||||
# 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 <tt>Payment.find_all_by_amount(50, :order => "created_on")</tt>.
|
||||
#
|
||||
# == 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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue