From 281edce6db8accc7d4a0e9ab01892631d9d0ebc3 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Tue, 20 May 2008 20:50:46 +0100 Subject: Ensure nil to '' doesn't get recorded by dirty for nullable integer columns. [#150 state:resolved] [Jason Dew, Pratik] --- activerecord/lib/active_record/dirty.rb | 24 ++++++++++++++++-------- activerecord/test/cases/dirty_test.rb | 10 ++++++++++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/activerecord/lib/active_record/dirty.rb b/activerecord/lib/active_record/dirty.rb index 6034963811..49f1204fa1 100644 --- a/activerecord/lib/active_record/dirty.rb +++ b/activerecord/lib/active_record/dirty.rb @@ -117,14 +117,7 @@ module ActiveRecord # The attribute already has an unsaved change. unless changed_attributes.include?(attr) old = clone_attribute_value(:read_attribute, attr) - - # Remember the original value if it's different. - typecasted = if column = column_for_attribute(attr) - column.type_cast(value) - else - value - end - changed_attributes[attr] = old unless old == typecasted + changed_attributes[attr] = old if field_changed?(attr, old, value) end # Carry on. @@ -138,5 +131,20 @@ module ActiveRecord update_without_dirty end end + + def field_changed?(attr, old, value) + if column = column_for_attribute(attr) + if column.type == :integer && column.null && old.nil? + # For nullable integer columns, NULL gets stored in database for blank (i.e. '') values. + # Hence we don't record it as a change if the value changes from nil to ''. + value = nil if value.blank? + else + value = column.type_cast(value) + end + end + + old != value + end + end end diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb index 1266eb5036..62178977f9 100644 --- a/activerecord/test/cases/dirty_test.rb +++ b/activerecord/test/cases/dirty_test.rb @@ -44,6 +44,16 @@ class DirtyTest < ActiveRecord::TestCase assert_nil pirate.catchphrase_change end + def test_nullable_integer_not_marked_as_changed_if_new_value_is_blank + pirate = Pirate.new + + ["", nil].each do |value| + pirate.parrot_id = value + assert !pirate.parrot_id_changed? + assert_nil pirate.parrot_id_change + end + end + def test_object_should_be_changed_if_any_attribute_is_changed pirate = Pirate.new assert !pirate.changed? -- cgit v1.2.3 From 19d7b1d22bd68af00244ddc3e1f35cec187e9120 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Wed, 21 May 2008 10:46:28 +0100 Subject: Verbose ActiveRecord::AssociationTypeMismatch exception message. [#189 state:resolved] --- activerecord/lib/active_record/associations/association_proxy.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations/association_proxy.rb b/activerecord/lib/active_record/associations/association_proxy.rb index ec16af3897..11c64243a2 100644 --- a/activerecord/lib/active_record/associations/association_proxy.rb +++ b/activerecord/lib/active_record/associations/association_proxy.rb @@ -210,7 +210,8 @@ module ActiveRecord def raise_on_type_mismatch(record) unless record.is_a?(@reflection.klass) - raise ActiveRecord::AssociationTypeMismatch, "#{@reflection.klass} expected, got #{record.class}" + message = "#{@reflection.class_name}(##{@reflection.klass.object_id}) expected, got #{record.class}(##{record.class.object_id})" + raise ActiveRecord::AssociationTypeMismatch, message end end -- cgit v1.2.3 From 6e3521e6134e7f0d0b27834266e41354290c4e7e Mon Sep 17 00:00:00 2001 From: Erkki Eilonen Date: Wed, 14 May 2008 17:07:21 +0300 Subject: Improve check_box_checked? to use include? for Array values. [#193 state:resolved] Signed-off-by: Pratik Naik --- actionpack/lib/action_view/helpers/form_helper.rb | 2 ++ actionpack/test/template/form_helper_test.rb | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 6d97038da9..0962be2c79 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -616,6 +616,8 @@ module ActionView value != 0 when String value == checked_value + when Array + value.include?(checked_value) else value.to_i != 0 end diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 4538b6dc6f..af99e6243d 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -181,6 +181,17 @@ class FormHelperTest < ActionView::TestCase '', check_box("post", "secret?") ) + + @post.secret = ['0'] + assert_dom_equal( + '', + check_box("post", "secret") + ) + @post.secret = ['1'] + assert_dom_equal( + '', + check_box("post", "secret") + ) end def test_check_box_with_explicit_checked_and_unchecked_values -- cgit v1.2.3 From 262d23d763c05bbe5f433a99cb9f02e48a8cdd4a Mon Sep 17 00:00:00 2001 From: Ryan Bates Date: Wed, 21 May 2008 08:27:20 -0700 Subject: ActiveRecord::Base#reload should clear dirty attributes. [#231 state:resolved] Signed-off-by: Pratik Naik --- activerecord/lib/active_record/dirty.rb | 8 ++++++++ activerecord/test/cases/dirty_test.rb | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/activerecord/lib/active_record/dirty.rb b/activerecord/lib/active_record/dirty.rb index 49f1204fa1..8fdc763292 100644 --- a/activerecord/lib/active_record/dirty.rb +++ b/activerecord/lib/active_record/dirty.rb @@ -40,6 +40,7 @@ module ActiveRecord base.alias_method_chain :save, :dirty base.alias_method_chain :save!, :dirty base.alias_method_chain :update, :dirty + base.alias_method_chain :reload, :dirty base.superclass_delegating_accessor :partial_updates base.partial_updates = false @@ -84,6 +85,13 @@ module ActiveRecord status end + # reload the record and clears changed attributes. + def reload_with_dirty(*args) #:nodoc: + record = reload_without_dirty(*args) + changed_attributes.clear + record + end + private # Map of change attr => original value. def changed_attributes diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb index 62178977f9..c011ffaf57 100644 --- a/activerecord/test/cases/dirty_test.rb +++ b/activerecord/test/cases/dirty_test.rb @@ -137,6 +137,14 @@ class DirtyTest < ActiveRecord::TestCase check_pirate_after_save_failure(pirate) end + def test_reload_should_clear_changed_attributes + pirate = Pirate.create!(:catchphrase => "shiver me timbers") + pirate.catchphrase = "*hic*" + assert pirate.changed? + pirate.reload + assert !pirate.changed? + end + private def with_partial_updates(klass, on = true) old = klass.partial_updates? -- cgit v1.2.3 From dd9938a44ee3a7bb6c42527a1be6fcec70bf4772 Mon Sep 17 00:00:00 2001 From: Frederick Cheung Date: Wed, 21 May 2008 21:03:38 +0100 Subject: Fix mysql 4.1 incompatibility in the active record schema tests. Signed-off-by: Michael Koziarski [#233 state:resolved ] --- .../test/cases/active_schema_test_mysql.rb | 73 ++++++++++++---------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/activerecord/test/cases/active_schema_test_mysql.rb b/activerecord/test/cases/active_schema_test_mysql.rb index ddf3e82162..2a42dc3517 100644 --- a/activerecord/test/cases/active_schema_test_mysql.rb +++ b/activerecord/test/cases/active_schema_test_mysql.rb @@ -40,47 +40,56 @@ class ActiveSchemaTest < ActiveRecord::TestCase end def test_add_timestamps - #we need to actually modify some data, so we make execute to point to the original method - ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do - alias_method :execute_with_stub, :execute - alias_method :execute, :execute_without_stub - end - ActiveRecord::Base.connection.create_table :delete_me do |t| - end - ActiveRecord::Base.connection.add_timestamps :delete_me - assert_equal ActiveRecord::Base.connection.execute("SHOW FIELDS FROM delete_me where FIELD='updated_at' AND TYPE='datetime'").num_rows, 1 - assert_equal ActiveRecord::Base.connection.execute("SHOW FIELDS FROM delete_me where FIELD='created_at' AND TYPE='datetime'").num_rows, 1 - ensure - ActiveRecord::Base.connection.drop_table :delete_me rescue nil - #before finishing, we restore the alias to the mock-up method - ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do - alias_method :execute, :execute_with_stub + with_real_execute do + begin + ActiveRecord::Base.connection.create_table :delete_me do |t| + end + ActiveRecord::Base.connection.add_timestamps :delete_me + assert column_present?('delete_me', 'updated_at', 'datetime') + assert column_present?('delete_me', 'created_at', 'datetime') + ensure + ActiveRecord::Base.connection.drop_table :delete_me rescue nil + end end end def test_remove_timestamps - #we need to actually modify some data, so we make execute to point to the original method - ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do - alias_method :execute_with_stub, :execute - alias_method :execute, :execute_without_stub - end - ActiveRecord::Base.connection.create_table :delete_me do |t| - t.timestamps - end - ActiveRecord::Base.connection.remove_timestamps :delete_me - assert_equal ActiveRecord::Base.connection.execute("SHOW FIELDS FROM delete_me where FIELD='updated_at' AND TYPE='datetime'").num_rows, 0 - assert_equal ActiveRecord::Base.connection.execute("SHOW FIELDS FROM delete_me where FIELD='created_at' AND TYPE='datetime'").num_rows, 0 - ensure - ActiveRecord::Base.connection.drop_table :delete_me rescue nil - #before finishing, we restore the alias to the mock-up method - ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do - alias_method :execute, :execute_with_stub + with_real_execute do + begin + ActiveRecord::Base.connection.create_table :delete_me do |t| + t.timestamps + end + ActiveRecord::Base.connection.remove_timestamps :delete_me + assert !column_present?('delete_me', 'updated_at', 'datetime') + assert !column_present?('delete_me', 'created_at', 'datetime') + ensure + ActiveRecord::Base.connection.drop_table :delete_me rescue nil + end end end - private + def with_real_execute + #we need to actually modify some data, so we make execute point to the original method + ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do + alias_method :execute_with_stub, :execute + alias_method :execute, :execute_without_stub + end + yield + ensure + #before finishing, we restore the alias to the mock-up method + ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do + alias_method :execute, :execute_with_stub + end + end + + def method_missing(method_symbol, *arguments) ActiveRecord::Base.connection.send(method_symbol, *arguments) end + + def column_present?(table_name, column_name, type) + results = ActiveRecord::Base.connection.select_all("SHOW FIELDS FROM #{table_name} LIKE '#{column_name}'") + results.first && results.first['Type'] == type + end end -- cgit v1.2.3 From 314e556e6fb7278e37f6105fedbe5fc51f7f848a Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 21 May 2008 11:54:24 -0700 Subject: Parentheses should be acceptable characters for auto_link_urls. [#234 state:resolved] Signed-off-by: Pratik Naik --- actionpack/lib/action_view/helpers/text_helper.rb | 2 +- actionpack/test/template/text_helper_test.rb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 55d2a68327..b710157f51 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -464,7 +464,7 @@ module ActionView [-\w]+ # subdomain or domain (?:\.[-\w]+)* # remaining subdomains or domain (?::\d+)? # port - (?:/(?:(?:[~\w\+@%=-]|(?:[,.;:][^\s$]))+)?)* # path + (?:/(?:(?:[~\w\+@%=\(\)-]|(?:[,.;:][^\s$]))+)?)* # path (?:\?[\w\+@%&=.;-]+)? # query string (?:\#[\w\-]*)? # trailing anchor ) diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb index 337697bf5c..36c939f761 100644 --- a/actionpack/test/template/text_helper_test.rb +++ b/actionpack/test/template/text_helper_test.rb @@ -186,6 +186,7 @@ class TextHelperTest < ActionView::TestCase http://en.wikipedia.org/wiki/Wikipedia:Today%27s_featured_picture_%28animation%29/January_20%2C_2007 http://www.mail-archive.com/rails@lists.rubyonrails.org/ http://www.amazon.com/Testing-Equal-Sign-In-Path/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1198861734&sr=8-1 + http://en.wikipedia.org/wiki/Sprite_(computer_graphics) ) urls.each do |url| -- cgit v1.2.3 From 4e084c3d9860c31fca21395c13031f04bb510b15 Mon Sep 17 00:00:00 2001 From: Ryan Bates Date: Wed, 21 May 2008 16:12:54 -0700 Subject: Add Rails.version. [#236 state:resolved] Signed-off-by: Pratik Naik --- railties/lib/commands/console.rb | 4 ++-- railties/lib/initializer.rb | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/railties/lib/commands/console.rb b/railties/lib/commands/console.rb index edffe4f1e6..2b9d92f647 100644 --- a/railties/lib/commands/console.rb +++ b/railties/lib/commands/console.rb @@ -24,9 +24,9 @@ ENV['RAILS_ENV'] = case ARGV.first end if options[:sandbox] - puts "Loading #{ENV['RAILS_ENV']} environment in sandbox (Rails #{Rails::VERSION::STRING})" + puts "Loading #{ENV['RAILS_ENV']} environment in sandbox (Rails #{Rails.version})" puts "Any modifications you make will be rolled back on exit" else - puts "Loading #{ENV['RAILS_ENV']} environment (Rails #{Rails::VERSION::STRING})" + puts "Loading #{ENV['RAILS_ENV']} environment (Rails #{Rails.version})" end exec "#{options[:irb]} #{libs} --simple-prompt" diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index dfd43042be..2e56485989 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -43,6 +43,10 @@ module Rails RAILS_CACHE end + def version + VERSION::STRING + end + def public_path @@public_path ||= self.root ? File.join(self.root, "public") : "public" end -- cgit v1.2.3 From c2036adf7658f56c924e2a206731ee63b628f34f Mon Sep 17 00:00:00 2001 From: Lawrence Pit Date: Thu, 22 May 2008 12:06:27 +0100 Subject: Show rails version when the server starts. [#235 state:resolved] Signed-off-by: Pratik Naik --- railties/lib/commands/servers/lighttpd.rb | 2 +- railties/lib/commands/servers/mongrel.rb | 2 +- railties/lib/commands/servers/webrick.rb | 2 +- railties/lib/rails/mongrel_server/commands.rb | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/railties/lib/commands/servers/lighttpd.rb b/railties/lib/commands/servers/lighttpd.rb index 07d4f9d0bf..c9d13e86f3 100644 --- a/railties/lib/commands/servers/lighttpd.rb +++ b/railties/lib/commands/servers/lighttpd.rb @@ -62,7 +62,7 @@ config = IO.read(config_file) default_port, default_ip = 3000, '0.0.0.0' port = config.scan(/^\s*server.port\s*=\s*(\d+)/).first rescue default_port ip = config.scan(/^\s*server.bind\s*=\s*"([^"]+)"/).first rescue default_ip -puts "=> Rails application starting on http://#{ip || default_ip}:#{port || default_port}" +puts "=> Rails #{Rails.version} application starting on http://#{ip || default_ip}:#{port || default_port}" tail_thread = nil diff --git a/railties/lib/commands/servers/mongrel.rb b/railties/lib/commands/servers/mongrel.rb index f59265e698..7bb110f63a 100644 --- a/railties/lib/commands/servers/mongrel.rb +++ b/railties/lib/commands/servers/mongrel.rb @@ -32,7 +32,7 @@ ARGV.clone.options do |opts| opts.parse! end -puts "=> Rails application starting on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}" +puts "=> Rails #{Rails.version} application starting on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}" parameters = [ "start", diff --git a/railties/lib/commands/servers/webrick.rb b/railties/lib/commands/servers/webrick.rb index b950376150..18c8897cc8 100644 --- a/railties/lib/commands/servers/webrick.rb +++ b/railties/lib/commands/servers/webrick.rb @@ -61,6 +61,6 @@ require 'webrick_server' OPTIONS['working_directory'] = File.expand_path(RAILS_ROOT) -puts "=> Rails application started on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}" +puts "=> Rails #{Rails.version} application started on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}" puts "=> Ctrl-C to shutdown server; call with --help for options" if OPTIONS[:server_type] == WEBrick::SimpleServer DispatchServlet.dispatch(OPTIONS) diff --git a/railties/lib/rails/mongrel_server/commands.rb b/railties/lib/rails/mongrel_server/commands.rb index 3786a56fde..0a92f418ad 100644 --- a/railties/lib/rails/mongrel_server/commands.rb +++ b/railties/lib/rails/mongrel_server/commands.rb @@ -119,7 +119,7 @@ module Rails config = RailsConfigurator.new(settings) do defaults[:log] = $stdout if defaults[:environment] == 'development' - Mongrel.log("=> Rails application starting on http://#{defaults[:host]}:#{defaults[:port]}") + Mongrel.log("=> Rails #{Rails.version} application starting on http://#{defaults[:host]}:#{defaults[:port]}") unless defaults[:daemon] Mongrel.log("=> Call with -d to detach") -- cgit v1.2.3 From cff2291df5d1df106ae8cf116655f0703f53f8c3 Mon Sep 17 00:00:00 2001 From: Frederick Cheung Date: Thu, 22 May 2008 11:19:10 +0100 Subject: Fix failing tests on mysql 4.1 & ruby 1.8.4. [#237 state:resolved] Signed-off-by: Pratik Naik --- activerecord/test/cases/migration_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 527856b4c0..f36255e209 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -281,7 +281,7 @@ if ActiveRecord::Base.connection.supports_migrations? # Do a manual insertion if current_adapter?(:OracleAdapter) Person.connection.execute "insert into people (id, wealth) values (people_seq.nextval, 12345678901234567890.0123456789)" - elsif current_adapter?(:OpenBaseAdapter) + elsif current_adapter?(:OpenBaseAdapter) || (current_adapter?(:MysqlAdapter) && Mysql.client_version < 50003) #before mysql 5.0.3 decimals stored as strings Person.connection.execute "insert into people (wealth) values ('12345678901234567890.0123456789')" else Person.connection.execute "insert into people (wealth) values (12345678901234567890.0123456789)" @@ -384,7 +384,7 @@ if ActiveRecord::Base.connection.supports_migrations? assert_not_equal "Z", bob.moment_of_truth.zone # US/Eastern is -5 hours from GMT assert_equal Rational(-5, 24), bob.moment_of_truth.offset - assert_equal "-05:00", bob.moment_of_truth.zone + assert_match /\A-05:?00\Z/, bob.moment_of_truth.zone #ruby 1.8.6 uses HH:MM, prior versions use HHMM assert_equal DateTime::ITALY, bob.moment_of_truth.start end end -- cgit v1.2.3