Re: RFC: Improving the rack parameter normalization

Andy Lowry
Fri, 14 Aug 2009 14:10:05 -0000

That could be part of a solution, but to make it dynamic would mean some
javascript to update the position fields as subforms are moved around by the
user, or just prior to submit. What I''m looking for is a
"dead-simple" way
of doing what seems a pretty obvious use-case, namely: the user gets to
reorder subforms via some drag-and-drop feature like the sortable_element
helper, and when the form is submitted, the order of the subforms at the
time of submission gets reflected in the database. Using hidden fields and
javascript to manipulate them seems unreasonably complicated when the
browsers are required to send form values in the order of appearance anyway,
since that''s the order we want for this use case. But the current rack
parameter parser either destroys the relative ordering of the subforms or
requires that the field names & ids be identical from one subform to the
next. The latter results in illegal HTML, potential mixing of subform data,
and an inability to use checkboxes and radio groups properly in the
subforms. Hence you can''t really take advantage of this very convenient
browser behavior.
I''ve been away and hence quiet for a few days, but per recommendations
earlier in this thread, I''ll take it up with the rack community to see
about
making their parameter parser use ordered hashes (shouldn''t be a hard
sell,
since it''ll happen with ruby 1.9 anyway), and also a general cleanup of
the
current parser. I may also look into updates to the rails acts_as_list
plugin, which I think could make the whole thing fully automatic (so no need
for a controller hack to update subform positions).

-andy

On Sat, Aug 8, 2009 at 10:06 PM, Allen <blatyo@gmail.com> wrote:

>
> Unless I''m missing something, why wouldn''t you just use
hidden fields
> that indicate the order?
>
> On Aug 6, 11:06 pm, andy <andyrlo...@gmail.com> wrote:
> > I have struggled much of the day today to do something that on the
> > surface seems like it should be a piece of cake. But either
it''s not,
> > or I''m too dense to see the easy way to do it.
> >
> > I''m leaning toward modifying the rack parameter parser to (a)
make it
> > far cleaner and more intelligible than it currently is (including
> > documenting exactly what it does!), and (b) make it easy to do what
> > I''m after. I think I can do this in a mostly
backward-compatible
> > fashion, and could provide a compatibility mode if needed for anyone
> > who needs the old behavior.
> >
> > I''d appreciate any feedback the experts may have before I
embark on
> > this.
> >
> > Here''s a simplified version of what I''m trying to do
that ended up
> > being (I think) impossible without resorting to some javascript that
> > really should not be required:
> >
> > Say I''ve got a nested model structure that looks like this:
> >
> > class Project < ActiveRecord::Base
> >   has_many :tasks
> >   accepts_nested_parameters_for :tasks
> > end
> >
> > class Task < ActiveRecord::Base
> >   belongs_to :project
> > end
> >
> > I''d like to be able create an edit form for :project that
includes a
> > dynamically varying list of :task subforms. I''ll have a
delete button
> > next to each :task subform, and an "Add a Task" button at
the bottom
> > of the last. All fairly standard and not very hard, especially with
> > the new accepts_nested_parameters_for feature.
> >
> > But now here''s the kicker: I also want to use the
"sortable_element"
> > helper so that the user can reorder the tasks - including newly added
> > tasks - within the project. In order to save the final ordering, this
> > means I need to be able to detect, from the request parameters, the
> > order that the :task subforms appeared in the overall form at the time
> > it was submitted. This should be easy, because browsers are required
> > to send form parameters in the order in which they appear at the time
> > of submission, and sortable_element works by physically reordering the
> > subforms in the overall DOM structure.
> >
> > The problem is that rack loses this ordering information, and
I''m
> > pretty much convinced that it can''t be made to keep it. You
can ALMOST
> > get this to work by specifying :index=>'''' and
:child_index=>'''' in all
> > your fields_for calls. But this results in illegal HTML (strictly
> > speaking, though it works, at least in the browser I''ve
tried), and
> > it''s also slightly risky. The illegal part comes from the
fact that
> > you''ll end up with multiple input elements in your form that
have the
> > same id value. E.g. a text field for task ''name''
would appear in
> > every :task subform, and in each appearance it would carry the same id
> > value.  And not only would that be illegal, it would also make it
> > impossible to have per-subform radio button groups. The radio button
> > input elements would all have the same name across all subforms, so
> > they''d all be linked, rather than only within a subform.
> >
> > Even without those problems, the strategy is dangerous because of the
> > way rack detects when it''s time to start a new hash, rather
than
> > continuing to fill a current hash. This comes into play for a
> > parameter with a name like
''project[tasks_attributes][][name]''.  The
> > the empty brackets call for an array of hashes at that point in the
> > structure, and rack will look at whether ''name''
appears as a key in
> > the current last element of that array. If so, it opens up a new
> > element in the array, otherwise it adds to the current last element.
> >
> > This mechanism will fail if not all your subforms offer the same set
> > of fields. E.g you might have separate buttons for "add quick
task"
> > and "add task," both of which add the same sort of object,
but "add
> > quick task" provides an abbreviated form for easier entry.
You''d have
> > to add the other fields as hidden fields in the abbreviated subform in
> > order to be safe, and it''d probably be a hellish debugging
exercise to
> > figure that out!
> >
> > OK, so here''s my idea:
> >
> > 1. When "[]" appears in a parameter name it always indicates
an array
> > at that point in the structure. What fallows goes into a new element
> > at the end of the array, using logic equivalent to what is currently
> > provided by rack.
> > 2. When "[.index]" appears, what follows will be be added to
the hash
> > that is the current last element of the array. The leading dot
> > prevents this index from itself being a hash key in what would then
> > have to be a containing hash, rather than a containing array, so
> > ordering of the substructures is preserved.
> > 4. When "[+index]"  appears, a new hash is added to the end
of the
> > array, and what follows goes into that hash.
> > 5. When [index] appears in a parameter name (without leading dot or
> > plus), the index is treated as a hash key for what follows same as
> > current behavior.
> >
> > Here''s an example:
> >
> >    project[title]=''My Project''
> >    project[tasks_attributes][+0][id]=1
> >    project[tasks_attributes][.0][name]=Sleep
> >    project[tasks_attributes][+1][id]=5
> >    project[tasks_attributes][.1][id]=Sleep more
> >    project[id]=3
> >
> > The params structure would look like this:
> >    {:title=>"My Project", :id=>"3",
> >        :tasks_attributes=>[{:id=>"1",
:name=>"Sleep"},
> > {:id=>"5", :name=>"Sleep more"}]
> >    }
> >
> > The current rake parameter processor would yield (assuming dots and
> > pluses are removed from the above):
> >    {:title=>"My Project, :id=>"3".
> >
:tasks_attributes=>{"1"=>{:id=>"5",
:name=>"Sleep more"}, "0"=>
> > {:id=>"1", :name=>"Sleep"}}
> >    }
> >
> > With the new structure it would be simple matter for the controller to
> > take a pass through params[:project][:tasks_attributes] and
> > assign :position values for the benefit of acts_as_list in order to
> > retain the final subform ordering. With the current structure, one
> > would need to use a javascript callback before submit to add those
> > values to the DOM, or AJAX calls to update positions every time
> > something gets reordered. Neither would be all that difficult, but
> > it''s infuriating, all the required information is already
available
> > for free in the raw form submission.
> >
> > To make this really work well, the form helpers would also need to be
> > modified to make use of the enhanced naming scheme. If I do this, my
> > goal will be to do both the enhanced rack parameter parser and the
> > form helper modifications to take advantage.
> >
> > Thanks for any comments or recommendations.
> >
> > -andy
> >
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Core" group.
To post to this group, send email to rubyonrails-core@googlegroups.com
To unsubscribe from this group, send email to
rubyonrails-core+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/rubyonrails-core?hl=en
-~----------~----~----~----~------~----~------~--~---