Skip to content

Commit

Permalink
Merge 5876 to release.
Browse files Browse the repository at this point in the history
git-svn-id: http://svn-commit.rubyonrails.org/rails/branches/1-2-stable@6122 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information
NZKoz committed Feb 4, 2007
1 parent c4d8d97 commit 41108fe
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 2 deletions.
3 changes: 3 additions & 0 deletions activerecord/CHANGELOG
@@ -1,5 +1,8 @@
*SVN*

* Pass a range in :conditions to use the SQL BETWEEN operator. #6974 [dcmanges]
Student.find(:all, :conditions => { :grade => 9..12 })

* Don't create instance writer methods for class attributes. [Rick]

* When dealing with SQLite3, use the table_info pragma helper, so that the bindings can do some translation for when sqlite3 breaks incompatibly between point releases. [Jamis Buck]
Expand Down
17 changes: 15 additions & 2 deletions activerecord/lib/active_record/base.rb
Expand Up @@ -84,7 +84,7 @@ def initialize(errors)
# Conditions can either be specified as a string, array, or hash representing the WHERE-part of an SQL statement.
# The array form is to be used when the condition input is tainted and requires sanitization. The string form can
# be used for statements that don't involve tainted data. The hash form works much like the array form, except
# only equality is possible. Examples:
# only equality and range is possible. Examples:
#
# class User < ActiveRecord::Base
# def self.authenticate_unsafely(user_name, password)
Expand Down Expand Up @@ -120,6 +120,9 @@ def initialize(errors)
# Student.find(:all, :conditions => { :first_name => "Harvey", :status => 1 })
# Student.find(:all, :conditions => params[:student])
#
# A range may be used in the hash to use the SQL BETWEEN operator:
#
# Student.find(:all, :conditions => { :grade => 9..12 })
#
# == Overwriting default accessors
#
Expand Down Expand Up @@ -1264,6 +1267,7 @@ def attribute_condition(argument)
case argument
when nil then "IS ?"
when Array then "IN (?)"
when Range then "BETWEEN ? AND ?"
else "= ?"
end
end
Expand Down Expand Up @@ -1392,12 +1396,14 @@ def sanitize_sql(condition)
# # => "name='foo''bar' and group_id= 4"
# { :status => nil, :group_id => [1,2,3] }
# # => "status IS NULL and group_id IN (1,2,3)"
# { :age => 13..18 }
# # => "age BETWEEN 13 AND 18"
def sanitize_sql_hash(attrs)
conditions = attrs.map do |attr, value|
"#{table_name}.#{connection.quote_column_name(attr)} #{attribute_condition(value)}"
end.join(' AND ')

replace_bind_variables(conditions, attrs.values)
replace_bind_variables(conditions, expand_range_bind_variables(attrs.values))
end

# Accepts an array of conditions. The array has each value
Expand Down Expand Up @@ -1433,6 +1439,13 @@ def replace_named_bind_variables(statement, bind_vars) #:nodoc:
end
end

def expand_range_bind_variables(bind_vars) #:nodoc:
bind_vars.each_with_index do |var, index|
bind_vars[index, 1] = [var.first, var.last] if var.is_a?(Range)
end
bind_vars
end

def quote_bound_value(value) #:nodoc:
if value.respond_to?(:map) && !value.is_a?(String)
if value.respond_to?(:empty?) && value.empty?
Expand Down
10 changes: 10 additions & 0 deletions activerecord/test/finder_test.rb
Expand Up @@ -136,6 +136,16 @@ def test_find_on_hash_conditions
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :approved => true }) }
end

def test_find_on_hash_conditions_with_range
assert_equal [1,2], Topic.find(:all, :conditions => { :id => 1..2 }).map(&:id).sort
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :id => 2..3 }) }
end

def test_find_on_hash_conditions_with_multiple_ranges
assert_equal [1,2,3], Comment.find(:all, :conditions => { :id => 1..3, :post_id => 1..2 }).map(&:id).sort
assert_equal [1], Comment.find(:all, :conditions => { :id => 1..1, :post_id => 1..10 }).map(&:id).sort
end

def test_find_on_multiple_hash_conditions
assert Topic.find(1, :conditions => { :author_name => "David", :title => "The First Topic", :replies_count => 1, :approved => false })
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :author_name => "David", :title => "The First Topic", :replies_count => 1, :approved => true }) }
Expand Down

0 comments on commit 41108fe

Please sign in to comment.