From c2fbcba16d2349285368c86b849db946dc0e7d57 Mon Sep 17 00:00:00 2001 From: Ryan Bates Date: Tue, 27 May 2008 07:31:53 -0700 Subject: Ensure named_scope#empty? uses count query. [#262 state:resolved] Signed-off-by: Pratik Naik --- activerecord/lib/active_record/named_scope.rb | 6 +++++- activerecord/test/cases/named_scope_test.rb | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb index 69b7da7700..b0c8a8b815 100644 --- a/activerecord/lib/active_record/named_scope.rb +++ b/activerecord/lib/active_record/named_scope.rb @@ -102,7 +102,7 @@ module ActiveRecord attr_reader :proxy_scope, :proxy_options [].methods.each do |m| - unless m =~ /(^__|^nil\?|^send|^object_id$|class|extend|find|count|sum|average|maximum|minimum|paginate|first|last)/ + unless m =~ /(^__|^nil\?|^send|^object_id$|class|extend|find|count|sum|average|maximum|minimum|paginate|first|last|empty?)/ delegate m, :to => :proxy_found end end @@ -135,6 +135,10 @@ module ActiveRecord end end + def empty? + @found ? @found.empty? : count.zero? + end + protected def proxy_found @found || load_found diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb index 8f2fc53d67..d890cf7936 100644 --- a/activerecord/test/cases/named_scope_test.rb +++ b/activerecord/test/cases/named_scope_test.rb @@ -146,4 +146,12 @@ class NamedScopeTest < ActiveRecord::TestCase end end + def test_empty_should_not_load_results + topics = Topic.base + assert_queries(2) do + topics.empty? # use count query + topics.collect # force load + topics.empty? # use loaded (no query) + end + end end -- cgit v1.2.3 From 4d248543429918bc5a63e109e6f2327ffab9848b Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Wed, 28 May 2008 22:58:45 +0100 Subject: Ensure correct db time is reported in production logs. --- .../active_record/connection_adapters/abstract_adapter.rb | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 8c286f64db..f48b107a2a 100755 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -128,15 +128,11 @@ module ActiveRecord protected def log(sql, name) if block_given? - if @logger and @logger.debug? - result = nil - seconds = Benchmark.realtime { result = yield } - @runtime += seconds - log_info(sql, name, seconds) - result - else - yield - end + result = nil + seconds = Benchmark.realtime { result = yield } + @runtime += seconds + log_info(sql, name, seconds) + result else log_info(sql, name, 0) nil -- cgit v1.2.3 From abb1bd2efa43b8efbb3faf4ccfb9246704a9044c Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Thu, 29 May 2008 10:20:39 +0100 Subject: Ensure AssociationCollection#count works with empty condition. [#271 state:resolved] [Jan De Poorter] --- activerecord/lib/active_record/associations/has_many_association.rb | 2 +- activerecord/test/cases/associations/has_many_associations_test.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb index 963a938485..f584a97cbb 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -9,7 +9,7 @@ module ActiveRecord @reflection.klass.count_by_sql(@finder_sql) else column_name, options = @reflection.klass.send(:construct_count_options_from_args, *args) - options[:conditions] = options[:conditions].nil? ? + options[:conditions] = options[:conditions].blank? ? @finder_sql : @finder_sql + " AND (#{sanitize_sql(options[:conditions])})" options[:include] ||= @reflection.options[:include] diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 53b55022eb..cbc621b411 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -32,6 +32,10 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal 2, Firm.find(:first).plain_clients.count end + def test_counting_with_empty_hash_conditions + assert_equal 2, Firm.find(:first).plain_clients.count(:conditions => {}) + end + def test_counting_with_single_conditions assert_equal 2, Firm.find(:first).plain_clients.count(:conditions => '1=1') end -- cgit v1.2.3 From 235d635708dd72bee0828457af5397c79750483a Mon Sep 17 00:00:00 2001 From: Andrew White Date: Thu, 29 May 2008 12:59:29 +0100 Subject: Ensure :select passed in options overrides the one from the scope. [#239 state:resolved] Signed-off-by: Pratik Naik --- activerecord/lib/active_record/base.rb | 2 +- activerecord/test/cases/method_scoping_test.rb | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index c393128621..d2d9bda6ba 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1457,7 +1457,7 @@ module ActiveRecord #:nodoc: def construct_finder_sql(options) scope = scope(:find) - sql = "SELECT #{(scope && scope[:select]) || options[:select] || (options[:joins] && quoted_table_name + '.*') || '*'} " + sql = "SELECT #{options[:select] || (scope && scope[:select]) || (options[:joins] && quoted_table_name + '.*') || '*'} " sql << "FROM #{(scope && scope[:from]) || options[:from] || quoted_table_name} " add_joins!(sql, options, scope) diff --git a/activerecord/test/cases/method_scoping_test.rb b/activerecord/test/cases/method_scoping_test.rb index 4b5bd6c951..1a9a875730 100644 --- a/activerecord/test/cases/method_scoping_test.rb +++ b/activerecord/test/cases/method_scoping_test.rb @@ -50,6 +50,22 @@ class MethodScopingTest < ActiveRecord::TestCase end end + def test_scoped_find_select + Developer.with_scope(:find => { :select => "id, name" }) do + developer = Developer.find(:first, :conditions => "name = 'David'") + assert_equal "David", developer.name + assert !developer.has_attribute?(:salary) + end + end + + def test_options_select_replaces_scope_select + Developer.with_scope(:find => { :select => "id, name" }) do + developer = Developer.find(:first, :select => 'id, salary', :conditions => "name = 'David'") + assert_equal 80000, developer.salary + assert !developer.has_attribute?(:name) + end + end + def test_scoped_count Developer.with_scope(:find => { :conditions => "name = 'David'" }) do assert_equal 1, Developer.count -- cgit v1.2.3 From 2ce1be3ac4823ccdfbe36ff5548a562aa5106d2e Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 30 May 2008 04:16:57 -0700 Subject: Enable partial updates by default --- activerecord/lib/active_record/dirty.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/dirty.rb b/activerecord/lib/active_record/dirty.rb index 8fdc763292..b32e17e990 100644 --- a/activerecord/lib/active_record/dirty.rb +++ b/activerecord/lib/active_record/dirty.rb @@ -43,7 +43,7 @@ module ActiveRecord base.alias_method_chain :reload, :dirty base.superclass_delegating_accessor :partial_updates - base.partial_updates = false + base.partial_updates = true end # Do any attributes have unsaved changes? -- cgit v1.2.3 From 03ba5d7b5183e7cb199a21aa6e06d646f7a5cbfe Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Fri, 30 May 2008 04:36:00 -0700 Subject: Ensure query assertion counts are the same when partial updates are enabled --- activerecord/test/cases/associations/has_many_associations_test.rb | 2 ++ .../test/cases/associations/has_many_through_associations_test.rb | 1 + 2 files changed, 3 insertions(+) (limited to 'activerecord') diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index cbc621b411..dbfa025efb 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -350,6 +350,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal "Another Client", new_client.name assert new_client.new_record? assert_equal new_client, company.clients_of_firm.last + company.name += '-changed' assert_queries(2) { assert company.save } assert !new_client.new_record? assert_equal 2, company.clients_of_firm(true).size @@ -360,6 +361,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase new_clients = assert_no_queries { company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) } assert_equal 2, new_clients.size + company.name += '-changed' assert_queries(3) { assert company.save } assert_equal 3, company.clients_of_firm(true).size end diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index 5561361bca..05155f6303 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -59,6 +59,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase # * 2 new records = 4 # + 1 query to save the actual post = 5 assert_queries(5) do + posts(:thinking).body += '-changed' posts(:thinking).save end -- cgit v1.2.3 From f7015336f66d284cff8ecb89df9f430791ac57ea Mon Sep 17 00:00:00 2001 From: Ryan Bates Date: Sat, 31 May 2008 12:36:07 -0700 Subject: Fix default nil tests for MySQL 5.0.51 [#192 state:resolved] Signed-off-by: Joshua Peek --- activerecord/test/cases/defaults_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord') diff --git a/activerecord/test/cases/defaults_test.rb b/activerecord/test/cases/defaults_test.rb index bd19ffcc29..2ea85417da 100644 --- a/activerecord/test/cases/defaults_test.rb +++ b/activerecord/test/cases/defaults_test.rb @@ -5,7 +5,7 @@ require 'models/entrant' class DefaultTest < ActiveRecord::TestCase def test_nil_defaults_for_not_null_columns column_defaults = - if current_adapter?(:MysqlAdapter) + if current_adapter?(:MysqlAdapter) && Mysql.client_version < 50051 { 'id' => nil, 'name' => '', 'course_id' => nil } else { 'id' => nil, 'name' => nil, 'course_id' => nil } -- cgit v1.2.3 From 0580b31b36c0f7dd1a0f8bdd1b1806e3bd65b22d Mon Sep 17 00:00:00 2001 From: Tim Harper Date: Tue, 13 May 2008 19:17:40 -0600 Subject: belongs_to polymorphic association assignments update the foreign_id and foreign_type fields regardless of whether the record being assigned is new or not. fixes the following scenarios: * I have validates_inclusion_of on the type field for a polymorphic belongs_to association. I assign a new record to the model's polymorphic relationship of the proper type. validation fails because the type field has not been updated. * I replace the value for a ppolymorphic association to a new record of another class. The type field still says its the previous class, and the id field points to the previous record as well. [#191 state:closed] --- .../belongs_to_polymorphic_association.rb | 6 ++--- .../associations/belongs_to_associations_test.rb | 29 +++++++++++++++++++++- 2 files changed, 30 insertions(+), 5 deletions(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb b/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb index df4ae38f38..d8146daa54 100755 --- a/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb +++ b/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb @@ -7,10 +7,8 @@ module ActiveRecord else @target = (AssociationProxy === record ? record.target : record) - unless record.new_record? - @owner[@reflection.primary_key_name] = record.id - @owner[@reflection.options[:foreign_type]] = record.class.base_class.name.to_s - end + @owner[@reflection.primary_key_name] = record.id + @owner[@reflection.options[:foreign_type]] = record.class.base_class.name.to_s @updated = true end diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index 3073eae355..e0da8bfb7a 100755 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -12,6 +12,8 @@ require 'models/author' require 'models/tag' require 'models/tagging' require 'models/comment' +require 'models/sponsor' +require 'models/member' class BelongsToAssociationsTest < ActiveRecord::TestCase fixtures :accounts, :companies, :developers, :projects, :topics, @@ -381,5 +383,30 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert_raise(ActiveRecord::ReadOnlyRecord) { companies(:first_client).readonly_firm.save! } assert companies(:first_client).readonly_firm.readonly? end - + + def test_polymorphic_assignment_foreign_type_field_updating + # should update when assigning a saved record + sponsor = Sponsor.new + member = Member.create + sponsor.sponsorable = member + assert_equal "Member", sponsor.sponsorable_type + + # should update when assigning a new record + sponsor = Sponsor.new + member = Member.new + sponsor.sponsorable = member + assert_equal "Member", sponsor.sponsorable_type + end + + def test_polymorphic_assignment_updates_foreign_id_field_for_new_and_saved_records + sponsor = Sponsor.new + saved_member = Member.create + new_member = Member.new + + sponsor.sponsorable = saved_member + assert_equal saved_member.id, sponsor.sponsorable_id + + sponsor.sponsorable = new_member + assert_equal nil, sponsor.sponsorable_id + end end -- cgit v1.2.3 From ef0ea782b1f5cf7b08e74ea3002a16c708f66645 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sat, 31 May 2008 16:57:46 -0700 Subject: Added SQL escaping for :limit and :offset [#288 state:closed] (Aaron Bedra, Steven Bristol, Jonathan Wiess) --- .../abstract/database_statements.rb | 9 +++++++-- activerecord/test/cases/adapter_test.rb | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb index 16d405d3bd..5358491cde 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb @@ -106,11 +106,16 @@ module ActiveRecord # SELECT * FROM suppliers LIMIT 10 OFFSET 50 def add_limit_offset!(sql, options) if limit = options[:limit] - sql << " LIMIT #{limit}" + sql << " LIMIT #{sanitize_limit(limit)}" if offset = options[:offset] - sql << " OFFSET #{offset}" + sql << " OFFSET #{offset.to_i}" end end + sql + end + + def sanitize_limit(limit) + limit.to_s[/,/] ? limit.split(',').map{ |i| i.to_i }.join(',') : limit.to_i end # Appends a locking clause to an SQL statement. diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb index 91504af901..c77446f880 100644 --- a/activerecord/test/cases/adapter_test.rb +++ b/activerecord/test/cases/adapter_test.rb @@ -104,4 +104,24 @@ class AdapterTest < ActiveRecord::TestCase end end + def test_add_limit_offset_should_sanitize_sql_injection_for_limit_without_comas + sql_inject = "1 select * from schema" + assert_equal " LIMIT 1", @connection.add_limit_offset!("", :limit=>sql_inject) + if current_adapter?(:MysqlAdapter) + assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7) + else + assert_equal " LIMIT 1 OFFSET 7", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7) + end + end + + def test_add_limit_offset_should_sanitize_sql_injection_for_limit_with_comas + sql_inject = "1, 7 procedure help()" + if current_adapter?(:MysqlAdapter) + assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit=>sql_inject) + assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7) + else + assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit=>sql_inject) + assert_equal " LIMIT 1,7 OFFSET 7", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7) + end + end end -- cgit v1.2.3 From f6e921f9568d7f2e4807edf8728e6b0df8991816 Mon Sep 17 00:00:00 2001 From: "John D. Hume" Date: Wed, 28 May 2008 23:35:56 -0400 Subject: Substitute value into validates_format_of message Signed-off-by: Michael Koziarski --- activerecord/lib/active_record/validations.rb | 2 +- activerecord/test/cases/validations_test.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index 0e150bddb2..c97aafb126 100755 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -692,7 +692,7 @@ module ActiveRecord raise(ArgumentError, "A regular expression must be supplied as the :with option of the configuration hash") unless configuration[:with].is_a?(Regexp) validates_each(attr_names, configuration) do |record, attr_name, value| - record.errors.add(attr_name, configuration[:message]) unless value.to_s =~ configuration[:with] + record.errors.add(attr_name, configuration[:message] % value) unless value.to_s =~ configuration[:with] end end diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb index a4d9da4806..7b71647d25 100755 --- a/activerecord/test/cases/validations_test.rb +++ b/activerecord/test/cases/validations_test.rb @@ -583,6 +583,12 @@ class ValidationsTest < ActiveRecord::TestCase assert_nil t.errors.on(:title) end + def test_validate_format_with_formatted_message + Topic.validates_format_of(:title, :with => /^Valid Title$/, :message => "can't be %s") + t = Topic.create(:title => 'Invalid title') + assert_equal "can't be Invalid title", t.errors.on(:title) + end + def test_validates_inclusion_of Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ) ) -- cgit v1.2.3 From f9db7695fe3c148c8d1077f1564e5b94d126b83b Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sat, 31 May 2008 17:03:03 -0700 Subject: Making ready for release of 2.1 --- activerecord/CHANGELOG | 6 ++++-- activerecord/Rakefile | 2 +- activerecord/lib/active_record/version.rb | 4 ++-- activerecord/test/connections/native_mysql/connection.rb | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) (limited to 'activerecord') diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index 78082665a4..f901e432d5 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,6 +1,8 @@ -* Add first/last methods to associations/named_scope. Resolved #226. [Ryan Bates] +*2.1.0 (May 31st, 2008)* -*2.1.0 RC1 (May 11th, 2008)* +* Added SQL escaping for :limit and :offset #288 [Aaron Bedra, Steven Bristol, Jonathan Wiess] + +* Added first/last methods to associations/named_scope. Resolved #226. [Ryan Bates] * Ensure hm:t preloading honours reflection options. Resolves #137. [Frederick Cheung] diff --git a/activerecord/Rakefile b/activerecord/Rakefile index 043ab6d551..fc068b16c3 100755 --- a/activerecord/Rakefile +++ b/activerecord/Rakefile @@ -171,7 +171,7 @@ spec = Gem::Specification.new do |s| s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) } end - s.add_dependency('activesupport', '= 2.0.991' + PKG_BUILD) + s.add_dependency('activesupport', '= 2.1.0' + PKG_BUILD) s.files.delete FIXTURES_ROOT + "/fixture_database.sqlite" s.files.delete FIXTURES_ROOT + "/fixture_database_2.sqlite" diff --git a/activerecord/lib/active_record/version.rb b/activerecord/lib/active_record/version.rb index 1463e84764..aaadef9979 100644 --- a/activerecord/lib/active_record/version.rb +++ b/activerecord/lib/active_record/version.rb @@ -1,8 +1,8 @@ module ActiveRecord module VERSION #:nodoc: MAJOR = 2 - MINOR = 0 - TINY = 991 + MINOR = 1 + TINY = 0 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/activerecord/test/connections/native_mysql/connection.rb b/activerecord/test/connections/native_mysql/connection.rb index 1fab444e58..3ee031f384 100644 --- a/activerecord/test/connections/native_mysql/connection.rb +++ b/activerecord/test/connections/native_mysql/connection.rb @@ -12,13 +12,13 @@ ActiveRecord::Base.logger = RAILS_DEFAULT_LOGGER ActiveRecord::Base.configurations = { 'arunit' => { :adapter => 'mysql', - :username => 'rails', + :username => 'root', :encoding => 'utf8', :database => 'activerecord_unittest', }, 'arunit2' => { :adapter => 'mysql', - :username => 'rails', + :username => 'root', :database => 'activerecord_unittest2' } } -- cgit v1.2.3 From ea03b0885c110003496c1f99dc7d9d2f1534955b Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sat, 31 May 2008 17:07:44 -0700 Subject: revert mysql test credential change --- activerecord/test/connections/native_mysql/connection.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord') diff --git a/activerecord/test/connections/native_mysql/connection.rb b/activerecord/test/connections/native_mysql/connection.rb index 3ee031f384..1fab444e58 100644 --- a/activerecord/test/connections/native_mysql/connection.rb +++ b/activerecord/test/connections/native_mysql/connection.rb @@ -12,13 +12,13 @@ ActiveRecord::Base.logger = RAILS_DEFAULT_LOGGER ActiveRecord::Base.configurations = { 'arunit' => { :adapter => 'mysql', - :username => 'root', + :username => 'rails', :encoding => 'utf8', :database => 'activerecord_unittest', }, 'arunit2' => { :adapter => 'mysql', - :username => 'root', + :username => 'rails', :database => 'activerecord_unittest2' } } -- cgit v1.2.3 From 72483c0d4c1e4ea794919974100acc2f255f6fd2 Mon Sep 17 00:00:00 2001 From: rick Date: Sat, 31 May 2008 17:13:11 -0700 Subject: Add ActiveRecord::Base.sti_name that checks ActiveRecord::Base#store_full_sti_class? and returns either the full or demodulized name. [rick] [#114 state:resolved] --- activerecord/CHANGELOG | 2 ++ .../associations/has_many_through_association.rb | 2 +- activerecord/lib/active_record/base.rb | 16 ++++++++++++---- activerecord/test/cases/inheritance_test.rb | 18 +++++++++++++++++- 4 files changed, 32 insertions(+), 6 deletions(-) (limited to 'activerecord') diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index 78082665a4..31e1c22f0d 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,3 +1,5 @@ +* Add ActiveRecord::Base.sti_name that checks ActiveRecord::Base#store_full_sti_class? and returns either the full or demodulized name. [rick] + * Add first/last methods to associations/named_scope. Resolved #226. [Ryan Bates] *2.1.0 RC1 (May 11th, 2008)* diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb index ebcf462f2e..52ced36d16 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -237,7 +237,7 @@ module ActiveRecord end def build_sti_condition - "#{@reflection.through_reflection.quoted_table_name}.#{@reflection.through_reflection.klass.inheritance_column} = #{@reflection.klass.quote_value(@reflection.through_reflection.klass.name.demodulize)}" + "#{@reflection.through_reflection.quoted_table_name}.#{@reflection.through_reflection.klass.inheritance_column} = #{@reflection.klass.quote_value(@reflection.through_reflection.klass.sti_name)}" end alias_method :sql_conditions, :conditions diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index d2d9bda6ba..92a24ecc5f 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1293,6 +1293,10 @@ module ActiveRecord #:nodoc: super end + def sti_name + store_full_sti_class ? name : name.demodulize + end + private def find_initial(options) options.update(:limit => 1) @@ -1452,7 +1456,11 @@ module ActiveRecord #:nodoc: # Nest the type name in the same module as this class. # Bar is "MyApp::Business::Bar" relative to MyApp::Business::Foo def type_name_with_module(type_name) - (/^::/ =~ type_name) ? type_name : "#{parent.name}::#{type_name}" + if store_full_sti_class + type_name + else + (/^::/ =~ type_name) ? type_name : "#{parent.name}::#{type_name}" + end end def construct_finder_sql(options) @@ -1571,8 +1579,8 @@ module ActiveRecord #:nodoc: def type_condition quoted_inheritance_column = connection.quote_column_name(inheritance_column) - type_condition = subclasses.inject("#{quoted_table_name}.#{quoted_inheritance_column} = '#{store_full_sti_class ? name : name.demodulize}' ") do |condition, subclass| - condition << "OR #{quoted_table_name}.#{quoted_inheritance_column} = '#{store_full_sti_class ? subclass.name : subclass.name.demodulize}' " + type_condition = subclasses.inject("#{quoted_table_name}.#{quoted_inheritance_column} = '#{sti_name}' ") do |condition, subclass| + condition << "OR #{quoted_table_name}.#{quoted_inheritance_column} = '#{subclass.sti_name}' " end " (#{type_condition}) " @@ -2508,7 +2516,7 @@ module ActiveRecord #:nodoc: # Message class in that example. def ensure_proper_type unless self.class.descends_from_active_record? - write_attribute(self.class.inheritance_column, store_full_sti_class ? self.class.name : self.class.name.demodulize) + write_attribute(self.class.inheritance_column, self.class.sti_name) end end diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb index 27394924a1..f09b617e6d 100755 --- a/activerecord/test/cases/inheritance_test.rb +++ b/activerecord/test/cases/inheritance_test.rb @@ -5,7 +5,23 @@ require 'models/subscriber' class InheritanceTest < ActiveRecord::TestCase fixtures :companies, :projects, :subscribers, :accounts - + + def test_class_with_store_full_sti_class_returns_full_name + old = ActiveRecord::Base.store_full_sti_class + ActiveRecord::Base.store_full_sti_class = true + assert_equal 'Namespaced::Company', Namespaced::Company.sti_name + ensure + ActiveRecord::Base.store_full_sti_class = old + end + + def test_class_without_store_full_sti_class_returns_demodulized_name + old = ActiveRecord::Base.store_full_sti_class + ActiveRecord::Base.store_full_sti_class = false + assert_equal 'Company', Namespaced::Company.sti_name + ensure + ActiveRecord::Base.store_full_sti_class = old + end + def test_should_store_demodulized_class_name_with_store_full_sti_class_option_disabled old = ActiveRecord::Base.store_full_sti_class ActiveRecord::Base.store_full_sti_class = false -- cgit v1.2.3 From 3282bf3b5016f0c9028cfff1012e8c31a13b40b7 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 1 Jun 2008 09:15:11 -0700 Subject: Added SQL escaping for :limit and :offset in MySQL [Jonathan Wiess] --- activerecord/CHANGELOG | 5 +++++ activerecord/lib/active_record/connection_adapters/mysql_adapter.rb | 3 ++- activerecord/test/cases/adapter_test.rb | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'activerecord') diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index 1c7c977141..a65771648e 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,3 +1,8 @@ +*Edge* + +* Added SQL escaping for :limit and :offset in MySQL [Jonathan Wiess] + + *2.1.0 (May 31st, 2008)* * Add ActiveRecord::Base.sti_name that checks ActiveRecord::Base#store_full_sti_class? and returns either the full or demodulized name. [rick] diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index f00a2c8950..653b45021d 100755 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -336,10 +336,11 @@ module ActiveRecord def add_limit_offset!(sql, options) #:nodoc: if limit = options[:limit] + limit = sanitize_limit(limit) unless offset = options[:offset] sql << " LIMIT #{limit}" else - sql << " LIMIT #{offset}, #{limit}" + sql << " LIMIT #{offset.to_i}, #{limit}" end end end diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb index c77446f880..11f9870534 100644 --- a/activerecord/test/cases/adapter_test.rb +++ b/activerecord/test/cases/adapter_test.rb @@ -118,7 +118,7 @@ class AdapterTest < ActiveRecord::TestCase sql_inject = "1, 7 procedure help()" if current_adapter?(:MysqlAdapter) assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit=>sql_inject) - assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7) + assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit=> '1 ; DROP TABLE USERS', :offset=>7) else assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit=>sql_inject) assert_equal " LIMIT 1,7 OFFSET 7", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7) -- cgit v1.2.3