Why don't form helpers read custom model attributes ?

Nicolas Blanco wrote:

I'm using custom read and write accessors in my models like :

class Order < ActiveRecord::Base

...

def date
  read_attribute(:date).strftime('%d/%m/%Y')
end

...

end

My problem is that Form helpers like text_field, text_area, etc, don't seem to work with these custom accessors, is that normal ?

In order to preserve both database field formats and redisplayed
user input, AR form helpers get their display strings from
<attribute>_before_type_cast methods.

So you could write:

def date_before_type_cast
   date.strftime('%d/%m/%Y')
end

But if you want a common date display format throughout your app,
instead add

ActiveSupport::CoreExtensions::date::Conversions::DATE_FORMATS[:default] = '%d/%m/%Y'

to environment.rb, and write in your model

def date_before_type_cast
   date.to_s
end

You'll also need a setter

def date=(val)
   self[:date] = val.is_a?(String) ? val.to_date : val
end

plus, since Rails does not currently support non-US formats for
string-to-date conversions, you'll have to add this to environment.rb

class String
   def to_date
     Date.strptime(self, '%d/%m/%Y')
   end
end

Mark Reginald James wrote:

Nicolas Blanco wrote:

> I'm using custom read and write accessors in my models like :
>
> class Order < ActiveRecord::Base
>
> ...
>
> def date
> read_attribute(:date).strftime('%d/%m/%Y')
> end
>
> ...
>
> end
>
> My problem is that Form helpers like text_field, text_area, etc, don't
> seem to work with these custom accessors, is that normal ?

In order to preserve both database field formats and redisplayed
user input, AR form helpers get their display strings from
<attribute>_before_type_cast methods.

So you could write:

def date_before_type_cast
   date.strftime('%d/%m/%Y')
end

But if you want a common date display format throughout your app,
instead add

ActiveSupport::CoreExtensions::date::Conversions::DATE_FORMATS[:default] = '%d/%m/%Y'

to environment.rb, and write in your model

def date_before_type_cast
   date.to_s
end

You'll also need a setter

def date=(val)
   self[:date] = val.is_a?(String) ? val.to_date : val
end

plus, since Rails does not currently support non-US formats for
string-to-date conversions, you'll have to add this to environment.rb

class String
   def to_date
     Date.strptime(self, '%d/%m/%Y')
   end
end

--
We develop, watch us RoR, in numbers too big to ignore.

I strongly recommend that you DO NOT CHANGE THE DEFAULT DATE FORMAT.
This will lead to unending pain and suffering, and will highly
displease the gods of MySQL.

If you change the default date format, rails will use this format to
try and write dates to the db. Mostl likely this will result in a
silent failure (at least in MySQL). Your dates will just get recorded
as '0000-00-00', and you will lose fistfuls of hair trying to figure
out why.

See tickets #6019 and #6363

_Kevin