Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #4676 (closed defect: wontfix)

Opened 2 years ago

Last modified 2 years ago

Rails is changing attribute values from String to Fixnum in certain case

Reported by: mlaster@metavillage.com Assigned to: David
Priority: normal Milestone:
Component: ActiveRecord Version:
Severity: normal Keywords: unverified
Cc: jonathan@bluewire.net.nz

Description

I don't know the system well enough to fix this, but I was able to create a unit test that exhibits the problem:

The value of content is created with the string "6789", but t.content is the Fixnum 6789.

This bug is blocking my development of a database adapter (Ticket #4093)

def test_attribute_type_not_changed

value = "6789" t = Topic.new("content" => value) assert value.class == t.content.class, "Attribute value class changed!"

end

Change History

04/10/06 03:00:16 changed by jonathan@bluewire.net.nz

What type is the column in the database table?

If you've got an integer column, it will more than likely cast that string to an int.

04/10/06 04:07:36 changed by mlaster@metavillage.com

It is VARCHAR(65536), so it should be a string.

04/10/06 09:16:44 changed by nzkoz

  • severity changed from critical to normal.

What database are you using? rails will typecast the values of attributes based on what type the column has. perhaps the bug is with your adapter?

04/10/06 12:41:24 changed by mlaster@metavillage.com

  • summary changed from Rails is changing attribute values from String to Fixnum in certain cases to Rails is changing attribute values from String to Fixnum in certain case.

I am writing an adapter for FrontBase. It is not the adapter because the data type in this test changes even if I use MySQL.

04/10/06 16:22:21 changed by david

  • keywords set to unverified.
  • status changed from new to closed.
  • resolution set to worksforme.

See the MySQL test cases. Varchars are not usually turned into fixnums. It's highly unlikely that this is a bug in Rails (since it would cause a ton of applications to explode). Please verify your adapter code and reopen if you can produce this error with a test case on one of the existing adapters.

04/10/06 17:12:28 changed by mlaster@metavillage.com

  • status changed from closed to reopened.
  • resolution deleted.

It is not my adapter code. I can add my test case to a fresh checkout of the trunk of Rails and reproduce the bug.

Add the following test to base_test.rb:

def test_attribute_type_not_changed

value = "6789" t = Topic.new("content" => value) assert value.class == t.content.class, "Attribute value class changed!"

end

And even MySQL will fail:

ruby -I "connections/native_mysql" base_test.rb

Using native MySQL Loaded suite base_test Started ....F................................................................................................................ Finished in 3.164022 seconds.

1) Failure:

test_attribute_type_not_changed(BasicsTest) [base_test.rb:1278]: Attribute value class changed!. <false> is not true.

117 tests, 297 assertions, 1 failures, 0 errors

It fails because t.content.class returns "Fixnum" instead of "String".

04/10/06 17:14:17 changed by mlaster@metavillage.com

Formatting was off on my prior post. The test case code is:

def test_attribute_type_not_changed
  value = "6789"
  t = Topic.new("content" => value)
  assert value.class == t.content.class, "Attribute value class changed!"
end

04/13/06 17:12:10 changed by mlaster@metavillage.com

In the test case, if "6789" is changed to "6789x" the test passes because "6789x" does not convert to a Fixnum. Changing the data type based on the content of the string seems like a bug to me.

04/15/06 12:08:31 changed by mlaster@metavillage.com

The content attribute on Topic is marked as serializable, so this bug may be related to that.

It appears that unserialize_attribute is being called in cases when the attribute is not YAML encoded.

The correct behavior would be:

irb(main):021:0> YAML::load("--- \"1234\"\n") => "1234"

But trying to decode a string that is not YAML will give the behavior I am seeing:

irb(main):022:0> YAML::load("1234") => 1234

07/08/06 01:30:45 changed by bitsweat

  • status changed from reopened to closed.
  • resolution set to wontfix.

Loading as YAML is the default fallback. It's necessary to be compatible with multiple versions of YAML across Ruby 1.8.x.