Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

text_field() does not use overridden model accessors

#3374

The following is an old problem, which still hasn't been fixed.

I couldn't find the same issue on Lighthouse, so I submitted the ticket again. If you this is a duplicate please feel free to delete it, but I can confirm the problem still exists in 2.3.4 and it feels like it should be fixed! (there is even a patch already)

This was the original ticket on Trac: http://dev.rubyonrails.org/ticket/3519

When utilizing text_field, the value of the text field when the form is populated from the database is not being pulled from the overridden Model accessor, but is instead being directly pulled from the Model. Example:

In the View: <%= text_field( 'db', 'name' ) %>

In the Model:

def name
  # Return the name of the db, less the prepend of 'sitename_' name = read_attribute(:name) site = self.site return name = name.gsub(site.name + "_",)
end

This overridden method works great when calling db.name.

Expected result: text_field uses overridden method like everyone else. Actual result: text_field just grabs the direct data.

Reported by Dennis Theisen · October 14th, 2009 @ 02:23 AM

State: committed
Milestone: 3.0.2
Assigned to: Santiago Pastorino Santiago Pastorino
Importance: Low

Activity

  1. Dennis Theisen
    Dennis Theisen
    • Tag changed from text_field to form_for, text_field

    October 14th, 2009 @ 02:24 AM

  2. Rohit Arondekar
    Rohit Arondekar
    • Assigned user set to Rohit Arondekar

    Dennis, can you confirm if this issue still exists on 2.3.8 and Rails master?

    June 15th, 2010 @ 02:31 PM

  3. Rohit Arondekar
    Rohit Arondekar
    • Tag changed from form_for, text_field to accessor, form_for, text_field
    • State changed from new to open
    • Assigned user changed from Rohit Arondekar to Jeremy Kemper

    I can confirm this issue exists on Rails master.

    The model has a title field.

    class Post < ActiveRecord::Base
      def title
        "blah blah"
      end
    end
    

    The edit form that should show "blah blah" in the text field.

    <%= form_for(@post) do |f| %>
      <div class="field">
        <%= f.label :title %><br />
        <%= f.text_field :title %>
      </div>
      <div class="actions">
        <%= f.submit %>
      </div>
    <% end %>
    

    It fetches the text directly from the DB bypassing the title method.

    June 16th, 2010 @ 03:01 AM

  4. Rohit Arondekar
    Rohit Arondekar

    Can somebody please confirm on the 2-3-stable branch or 2.3.8?

    June 16th, 2010 @ 03:02 AM

  5. Sam Soffes
    Sam Soffes
    • Tag changed from accessor, form_for, text_field to form_for, text_field
    • Assigned user changed from Jeremy Kemper to Rohit Arondekar

    I just tested this in Rails 3.0.0.beta4 and experienced the same problem.

    I created a new app, ran rails g migration post title:string, and made post look like this:

    class Post < ActiveRecord::Base
      def title
        "blah blah"
      end
    end
    

    The textfield in both the new and edit, didn't show "blah blah" as the title, but an empty string or what was in the database in edit action. In the console, it behaved as expected.

    June 16th, 2010 @ 03:04 AM

  6. Rohit Arondekar
    Rohit Arondekar
    • Assigned user changed from Rohit Arondekar to Jeremy Kemper

    June 16th, 2010 @ 03:10 AM

  7. Santiago Pastorino
  8. Santiago Pastorino
    Santiago Pastorino
    • Milestone cleared.
    • Assigned user changed from Jeremy Kemper to Santiago Pastorino

    June 18th, 2010 @ 11:04 PM

  9. Santiago Pastorino
  10. Miles Egan
    Miles Egan
    • Importance changed from to Low

    This seems to be a result of this definition in lib/action_view/form_helper.rb:

            def value_before_type_cast(object, method_name)
              unless object.nil?
                object.respond_to?(method_name + "_before_type_cast") ?
                object.send(method_name + "_before_type_cast") :
                object.send(method_name)
              end
            end
    

    Which means that we only call the native method if we can't find a corresponding before_type_cast version. This seems backwards. If we define an accessor that should take priority, right? Reversing the sense of this method to call method_name first and then fall back to before_type_cast doesn't seem to break any tests.

    July 16th, 2010 @ 06:38 AM

  11. Repository
  12. Repository
  13. Chris Wise
    Chris Wise

    With the commit to RC2, there are some side-effects to this with Time fields and MySQL (2.8.1 gem). It used to be that when text_field was used with a Time field (not Date), that the value would be rendered as "13:00:00" (as an example). Now it renders as "Sat Jan 01 13:00:00 UTC 2000".

    Is this more of a problem with the MySQL gem, or in ActiveRecord (I am sorry, I can't follow the code well enough to know)? Also in the committed fix (http://github.com/rails/rails/commit/fb0bd8c1092db51888ec4bb72af6c5..., why would the object.send(method_name + "_before_type_cast") be allowed w/o checking if the object respond to it (Again, I am weak at working through the code and trying to figure out if that method is required to be there for each attribute - maybe it is).

       def value_before_type_cast(object, method_name)
         unless object.nil?
           object.respond_to?(method_name) ?
           object.send(method_name) :
           object.send(method_name + "_before_type_cast")
         end
       end
    

    August 26th, 2010 @ 03:00 PM

  14. Chris Wise
    Chris Wise

    I rescind my comment. I was informed I was using mysql gem (2.8.1) and should've been using mysql2 gem instead. There is some funny behaviour from the mysql gem where I was getting an expected rendering as a time but that's apparently not what the behaviour is expected to be.

    August 26th, 2010 @ 03:34 PM

  15. Oliver Eilhard
    Oliver Eilhard

    The commit 8141f0894ecf869ee11f077e5b49e06669790632 seems to break a User in one of my applications that has a write-only password field.

    The User model comes with a password attribute which is write-only and hashed before written to the DB, so there's only the following code in the User model:

      def password=(cleartext_password)
        @password = cleartext_password
      end
    

    In the form I'm using the form helper like this:

      f.password_field :password
    

    Now when rendering the form, the form_helper is complaining about a missing password_before_type_cast method which it didn't before RC2.

    August 26th, 2010 @ 05:56 PM

  16. Repository
  17. Repository
  18. Noah
    Noah

    This commit makes the error message a bit obscure. If, for example, you use a custom Person object and present the field "name", but your Person object doesn't define name I would expect to see "undefined method name' for #<Person:0xf661188>" and not "undefined methodname_before_type_cast' for #<Person:0xf661188>"

    September 22nd, 2010 @ 03:20 AM

  19. Santiago Pastorino
  20. Tom Stuart
    Tom Stuart

    There's some complaining on the 2.3 backport, specifically about the fact that this breaks the behaviour whereby the user's original inputs (vs their typecasted equivalents) are kept on the form after a validation failure.

    No longer a problem for 2.3.x since it's been reverted on 2-3-stable, but out of interest, why's this not a problem for Rails 3 too?

    September 28th, 2010 @ 11:37 AM

  21. Santiago Pastorino
    Santiago Pastorino

    Tom we discussed about this and i'm going to revert it from Rails 3 too.

    September 28th, 2010 @ 05:40 PM

  22. Tom Stuart
    Tom Stuart

    Great, Santiago. Thanks for clarifying!

    September 29th, 2010 @ 09:07 AM

  23. Tom Stuart
    Tom Stuart

    Resolved by this commit, I believe. Thanks.

    October 11th, 2010 @ 06:32 AM

  24. Jeremy Kemper