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

Ticket #608 (closed defect: duplicate)

Opened 4 years ago

Last modified 1 year ago

[PATCH] Models for tables with numeric columns quietly insert zeroes on invalid user input

Reported by: dave@pragprog.com Assigned to: David
Priority: normal Milestone: 2.x
Component: ActiveRecord Version: edge
Severity: major Keywords: needy
Cc: bitsweat, Dee.Zsombor@gmail.com, michael@schuerig.de

Description

  • Create a table containing a numeric column.
  • Create a scaffold against that table
  • Ask that scaffold to create a new record. In the form that's displayed, enter 'wibble' in the field for the numeric column, and click [create].
  • The row will be created with zero in the column

To make the issue even worse, you can't validate the input by simply checking the attribute in a validation function. For example, if the column is called 'price', and you enter 'wibble' on the form, by the time you get to the validation function, the attribute 'price' wil already be set to 0. You have to instead manually validate against price_before_type_cast.

I'm guessing most Rails applications don't perform these checks, and that any that don't will silently accept bad data in numeric fields, storing 0 values in the table.

Attachments

numeric_columns_quietly_insert_zeroes.diff (3.1 kB) - added by Dee.Zsombor@gmail.com on 04/13/05 10:13:39.
numeric_columns_quietly_insert_zeroes2.diff (3.2 kB) - added by Dee.Zsombor@gmail.com on 04/14/05 02:14:42.
Second attempt
numeric_columns_quietly_insert_zeroes_autovalidation.diff (16.3 kB) - added by Dee.Zsombor@gmail.com on 04/17/05 10:17:46.
with_autovalidation.diff (24.1 kB) - added by Dee.Zsombor@gmail.com on 04/19/05 06:13:43.

Change History

02/15/05 14:07:04 changed by david

  • severity changed from major to enhancement.

This is a feature request in my eyes. There are lots of ways around it, but to have it automatically handled would be nicer.

02/19/05 03:49:10 changed by dave@pragprog.com

Let me explain why I think this is more serious than you might feel.

For you, this isn't an issue: I haven't seen any numeric fields on any of the sites you've created, and this has never bitten you.

However, I'm hoping to see Rails push Ruby into the mainstream. One of the things that is a passport for Rails is the scaffolding, and automatic form generation. So folks start using Rails, and the first thing they try is to create a scaffold. They bring up the app, type some stuff into fields, press enter, and discover that the values stored in the database are not what they typed. They go "hmm, let's try some other framework, this one is clearly buggy" and we lose a punter.

This isn't an obscure bug: I ran into it in the very first example I put together for the book.

Your call, but I had to vote at least once to have this treated more seriously.

Cheers

Dave

03/02/05 09:51:14 changed by nzkoz

  • severity changed from enhancement to major.
  • milestone set to 1.0.

I'm with Dave on this, after discussing it with David HH, i'm returning this to a bug.

We'll fix it before 1.0

04/13/05 10:13:39 changed by Dee.Zsombor@gmail.com

  • attachment numeric_columns_quietly_insert_zeroes.diff added.

04/13/05 10:29:28 changed by Dee.Zsombor@gmail.com

With last patch nil is inserted instead of zero, thus allowing validations to be performed on column name instead of column_before_type_cast. Note that validation is not added automatically.

04/13/05 11:06:00 changed by Dee.Zsombor@gmail.com

We could do following:

1) if column can be NULL, eval for all cloumns with numeric type

validates_numericality_of :column, :only_integer => true, :allow_nil => true

2) else eval

validates_numericality_of :column, :only_integer => true, :allow_nil => false

Currently can_be_null property of columns is not retrieved. I know that this would be possible with mysql, dont know about other databases and I cant try them out.

04/14/05 02:14:42 changed by Dee.Zsombor@gmail.com

  • attachment numeric_columns_quietly_insert_zeroes2.diff added.

Second attempt

04/14/05 02:18:55 changed by Dee.Zsombor@gmail.com

Typecasts to value instead of nil, still no automatic vaidation (yet).

04/14/05 02:50:28 changed by Dee.Zsombor@gmail.com

If we do automatic validation of numeric columns, we just as well add others things like:

* validates_presence_of attribute
* validates_length_of attribute, :maximum=>30
* validates_uniqueness_of attribute

To this date we are not inferring validations from database schema at all, instead we rely on the user to add them. Probably there is a reason for it, that is not clear to me. Any ideas?

04/17/05 10:17:46 changed by Dee.Zsombor@gmail.com

  • attachment numeric_columns_quietly_insert_zeroes_autovalidation.diff added.

04/17/05 10:21:35 changed by Dee.Zsombor@gmail.com

  • summary changed from Models for tables with numeric columns quietly insert zeroes on invalid user input to [PATCH] Models for tables with numeric columns quietly insert zeroes on invalid user input.

Numeric type conversion in low level adapters now return original unconverted value instead of zero or nil. Better to have an erroneous value than a silent conversion to something valid.

Rewrote validates_numericality_of, to check type of column value instead of relying regular expressions being applied to column_before_type_cast.

Inferred can_be_null column property from database. Note that this was only done for myqql. Other adapters should be modified also. I need a helping hand with this ...

Base#attributes_from_column_definition now uses Base#columns instead of going though connection adapter. I'm not sure if this was by design but fields where queried when there should have not been.

Implemented new autovalidation feature for integers and floats, by adding validates_numericality_of inside diverted method Base#column

Added table definition for mysql 'floattests'. Other adapters are missing this as I had no access each kind of database, and it did not want to play on changes that I cant verify at least syntactically. ValidationsTest.test_throw_away_typing thrown away (pun intended). ValidationsTest.test_validates_numericality_of removed some float test values as they failed autovalidation for integers. Perhaps this test case should be deleted also?

Introduced some new test cases: test_autovalidates_numericality_of_int_with_string_fail test_autovalidates_numericality_of_int_with_string_pass test_autovalidates_numericality_of_float_with_string_fail test_autovalidates_numericality_of_float_with_string_pass

04/19/05 06:13:43 changed by Dee.Zsombor@gmail.com

  • attachment with_autovalidation.diff added.

04/19/05 06:29:38 changed by Dee.Zsombor@gmail.com

Extended my previous patch do to autovalidation for validate_length_of. Validations can now be disabled globaly and for individual attributes. By default auto validation is on. This meant that some testcases broke, and other changes where needed also (like validate_length_of on Value clases).

See previous description for other changes.

04/27/05 01:41:08 changed by anonymous

  • version changed from 0.9.5 to 0.11.0.

06/08/05 02:37:52 changed by anonymous

  • cc set to Dee.Zsombor@gmail.com.

06/13/05 17:22:57 changed by minam

From what Dave originally said on this ticket, it sounds like the problem is mostly when using scaffolding. Perhaps the scaffolding could also auto-generate some validation code?

06/14/05 02:44:46 changed by Dee.Zsombor@gmail.com

Nope, it happens regardless of scaffolding or not. Problem is how typecasting is performed at connection adapter level. See relevant snippet from abstract_adapter.rb

 def type_cast(value)
        if value.nil? then return nil end
        case type
          when :string    then value
          when :text      then value
          when :integer   then value.to_i rescue value ? 1 : 0
# ... snip ...

If column was inferred to have type integer and you have a string value it will be casted to zero.

irb(main):002:0> "wibble".to_i
=> 0

I suggest performing the cast only if it is possible, otherwise original string value should be kept so that validation would be possible. Database will not let us save a string for an integer anyway. My second patch numeric_columns_quietly_insert_zeroes2.diff does exactly this.

Forth patch does autovalidation also so that non attentive users will get the benefit too.

09/11/05 16:49:33 changed by mschuerig

  • cc changed from Dee.Zsombor@gmail.com to Dee.Zsombor@gmail.com,michael@schuerig.de.

07/07/06 22:39:25 changed by bitsweat

  • cc changed from Dee.Zsombor@gmail.com,michael@schuerig.de to bitsweat, Dee.Zsombor@gmail.com, michael@schuerig.de.
  • milestone changed from 1.0 to 1.x.

Any progress on a fix + tests?

02/24/07 22:19:59 changed by josh

  • keywords set to needy.
  • version changed from 0.11.0 to edge.

02/24/07 22:38:00 changed by obrie

This sounds somewhat like the issue described in #6156 and fixed in [5901], [5902], [5903], and [5905]. Not sure if that's the case.

04/23/07 07:42:11 changed by Afroz

Issue still exists. I tried validating a numeric column using:

validates_format_of :num_variable, :with => /\A[0-9]+\Z/

Entering a string such as "wibble" does not throw an error. Instead 0 is entered into the column.

Currently using Rails 1.2.3.

10/15/07 00:40:11 changed by bitsweat

  • status changed from new to closed.
  • resolution set to duplicate.