Deprecation of :selected option
In the Formtastic 0.9.8 gem, there is a deprecation warning about :selected/:default/:checked values, this wiki page is being created in advance so we have somewhere to link to and point people to upon release.
Rails does a really bad job of the :selected option in its helpers. In most cases, using a :selected
option will override the value. If you’re using the same form partial or view for creating and editing your models, you’ll find that’s a pretty bad thing. There is at least one helper in which the :selected
option behaves more like a default, only applying this selection if the model doesn’t already have a value.
We think the latter default behaviour is much more ideal, so quite a bit of work was done to apply this, starting with a few hits-and-misses on the date and time inputs in the 0.9.7 gem (which has a bug), and then we stormed through every selectable input and try to apply this logic as a new :default
option, replacing and fixing the behaviour of :selected
and :checked
.
The issue we ran into is related to the logic of when to use the default value supplied by the Formtastic form DSL, and when to use the model’s existing value for the attribute.
The ideal trigger to show a default value is if the attribute is nil
, since an empty string (or an empty array of child objects), whilst empty, can still be a valid value (it’s ok for a Post’s description to be an empty string, it’s ok for a Post to have no tags). So, the trigger for using a default is if the object’s attribute is nil
, empty isn’t enough.
Here’s the problem. has_many
and has_and_belongs_to_many
associations are never nil
. An array is always returned, so there’s no way to discern if the association is intentionally empty (don’t apply the default) or not filled in yet (apply the default).
We tried to use the default only of the object is a new_record?
, but this would mean that the default form value would trump any previous selections on an unsaved record between requests (like, say, an object with some validation errors). No good.
It’s really important that the Formtastic DSL and behaviour is consistent and predictable. So, while this problem only exists for some inputs and associations, we’re not interested in having options that behave quite differently depending on the input type or association type.
Right now, we don’t have a solution, just a problem. There’s a pretty sucky :selected
implementation in 0.9.7, and there’s no candidate to replace it. This issue has paralysed and delayed the 0.9.8 gem a lot.
So, we’re deprecating the :selected
and :checked
options in 0.9.8. They’ll be removed from the 1.0 release, unless we come up with a decent solution between now and then.
Maybe we’re missing something cool in ActiveRecord. Maybe you have an insane solution. Please join the Formtastic Google group and get involved.
There’s two options. Either use an after_initialize
block in your model, or set-up the default values just after you instantiate your object in the controller. Examples:
class PostsController < ApplicationController def new @post = Post.new @post.title = "Untitled" # set a default title end end
class Post < ActiveRecord::Base after_inititalize :set_default_title #... protected def set_default_title self.title ||= "Untitled" end end
And you can still mix ERB and regular Rails helpers in with Formtastic helpers:
%li %label{:for => "banner_entity_type"} Associated with = f.select :entity_type, options_for_select(["Page", "Organization", "Promotion"], @banner.entity_type)