Without getting into the age-old discussion about the usefulness of NULL... There are plenty of applications that use and rely on them. It would seem that Rails would want to allow the insertion or update of a text/varchar column with a NULL value. I understand the need to maintain the current behaviour, and propose the following.
If a column is defined as NULL (i.e. not NOT NULL), then Rails should treat an empty string in form submission as NULL.
The argument against this is that it is a data change which should not be made for the developer "under the covers." I submit that this is what happens with INT and FLOAT (etc) already, so this is not violating any existing standards in Rails.
Since NULLability is checked prior to this rule, existing applications with columns that are NOT NULL would see existing behaviour, that is an empty string. Even if the column is NULLable, an empty string could be inserted if desired/required by attempting to insert one or more spaces (' ').
This change would also make the behaviour of validates_inclusion_of() make sense in the case of a TEXT/VARCHAR field that accepts nulls but also has a limited number of valid non-NULL options. Currently, :allow_nil is ignored in this validation rule, so the validation will never work with "blank" input.
Here is my proposed change, sorry it's not a patch, to lib/ruby/gems/1.8/gems/activerecord-1.13.0/lib/active_record/base.rb
# Updates the attribute identified by <tt>attr_name</tt> with the specified +value+. Empty strings for fixnum and float
# columns are turned into nil.
def write_attribute(attr_name, value)
attr_name = attr_name.to_s
if (column = column_for_attribute(attr_name)) && column.number?
@attributes[attr_name] = convert_number_column_value(value)
> elsif (column = column_for_attribute(attr_name)) && column.null
> @attributes[attr_name] = convert_nullable_column_value(value)
else
@attributes[attr_name] = value
end
end
> def convert_nullable_column_value(value)
> case value
> when '': nil
> else value
> end
> end
def convert_number_column_value(value)
case value
when FalseClass: 0
when TrueClass: 1
when '': nil
else value
end
end
Thank you!